深入理解Java泛型:概念、用法与案例分析

news2024/9/24 13:14:33

个人名片**
在这里插入图片描述
🎓作者简介:java领域优质创作者
🌐个人主页:码农阿豪
📞工作室:新空间代码工作室(提供各种软件服务)
💌个人邮箱:[2435024119@qq.com]
📱个人微信:15279484656
🌐个人导航网站:www.forff.top
💡座右铭:总有人要赢。为什么不能是我呢?

  • 专栏导航:

码农阿豪系列专栏导航
面试专栏:收集了java相关高频面试题,面试实战总结🍻🎉🖥️
Spring5系列专栏:整理了Spring5重要知识点与实战演练,有案例可直接使用🚀🔧💻
Redis专栏:Redis从零到一学习分享,经验总结,案例实战💐📝💡
全栈系列专栏:海纳百川有容乃大,可能你想要的东西里面都有🤸🌱🚀

目录

      • 深入理解Java泛型:概念、用法与案例分析
        • 一、泛型的基本概念
        • 二、泛型的使用
        • 三、泛型的高级用法
        • 四、泛型的最佳实践
        • 五、总结

深入理解Java泛型:概念、用法与案例分析

在Java编程中,泛型(Generics)是一个强大且重要的特性。它允许我们在编写类、接口和方法时引入类型参数,从而在不指定具体类型的情况下使用它们。泛型的主要目的是为了提高代码的重用性、类型安全性和可读性。本文将深入探讨Java泛型的概念、用法以及相关的代码案例。

一、泛型的基本概念
  1. 什么是泛型?

    泛型是一种允许在编写类、接口和方法时引入类型参数的机制。这意味着在使用这些泛型类或方法时,可以为其指定具体的类型。泛型通过减少类型转换和提高类型检查来提高代码的类型安全性。

  2. 泛型的语法

    在Java中,泛型使用尖括号<>来指定类型参数。例如:

    List<String> list = new ArrayList<>();
    

    在这个例子中,List<String>表示一个类型参数为String的列表。

二、泛型的使用
  1. 泛型类

    泛型类是指带有类型参数的类。下面是一个简单的泛型类的示例:

    public class Box<T> {
        private T content;
    
        public void setContent(T content) {
            this.content = content;
        }
    
        public T getContent() {
            return content;
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            Box<String> stringBox = new Box<>();
            stringBox.setContent("Hello, Generics!");
            System.out.println(stringBox.getContent());
    
            Box<Integer> integerBox = new Box<>();
            integerBox.setContent(123);
            System.out.println(integerBox.getContent());
        }
    }
    

    在这个例子中,Box<T>是一个泛型类,T是一个类型参数。可以看到,我们可以创建Box类的不同实例,使用不同的类型参数。

  2. 泛型方法

    泛型方法是指带有类型参数的方法。下面是一个泛型方法的示例:

    public class GenericMethodExample {
        public static <T> void printArray(T[] array) {
            for (T element : array) {
                System.out.print(element + " ");
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            Integer[] intArray = {1, 2, 3, 4, 5};
            String[] strArray = {"A", "B", "C", "D"};
    
            printArray(intArray); // 输出: 1 2 3 4 5
            printArray(strArray); // 输出: A B C D
        }
    }
    

    在这个例子中,printArray方法是一个泛型方法,它带有一个类型参数T,并可以接受一个T类型的数组作为参数。

  3. 泛型接口

    泛型接口是指带有类型参数的接口。下面是一个泛型接口的示例:

    public interface Pair<K, V> {
        K getKey();
        V getValue();
    }
    
    public class OrderedPair<K, V> implements Pair<K, V> {
        private K key;
        private V value;
    
        public OrderedPair(K key, V value) {
            this.key = key;
            this.value = value;
        }
    
        public K getKey() { return key; }
        public V getValue() { return value; }
    }
    
    public class Main {
        public static void main(String[] args) {
            Pair<String, Integer> p1 = new OrderedPair<>("Even", 8);
            Pair<String, String> p2 = new OrderedPair<>("hello", "world");
    
            System.out.println("Key: " + p1.getKey() + ", Value: " + p1.getValue());
            System.out.println("Key: " + p2.getKey() + ", Value: " + p2.getValue());
        }
    }
    

    在这个例子中,Pair<K, V>是一个泛型接口,OrderedPair<K, V>实现了这个接口。可以看到,我们可以使用不同的类型参数来创建OrderedPair的实例。

三、泛型的高级用法
  1. 有界类型参数

    有时候,我们希望限制类型参数必须是某个类的子类或者实现某个接口。可以使用extends关键字来实现这一点:

    public class BoundedTypeParameterExample {
        public static <T extends Number> void printNumber(T number) {
            System.out.println("Number: " + number);
        }
    
        public static void main(String[] args) {
            printNumber(123); // 输出: Number: 123
            printNumber(45.67); // 输出: Number: 45.67
            // printNumber("Hello"); // 编译错误,String不是Number的子类
        }
    }
    

    在这个例子中,T必须是Number类的子类,因此只能传递数字类型的参数。

  2. 通配符

    通配符?表示未知类型。通配符可以用在类或者方法的类型参数中。通配符有三种形式:

    • 无界通配符 ?:表示可以接受任何类型。

      public class UnboundedWildcardExample {
          public static void printList(List<?> list) {
              for (Object elem : list) {
                  System.out.print(elem + " ");
              }
              System.out.println();
          }
      
          public static void main(String[] args) {
              List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
              List<String> strList = Arrays.asList("A", "B", "C");
      
              printList(intList); // 输出: 1 2 3 4 5
              printList(strList); // 输出: A B C
          }
      }
      
    • 有限制通配符 ? extends T:表示可以接受类型为TT的子类。

      public class UpperBoundedWildcardExample {
          public static void printNumbers(List<? extends Number> list) {
              for (Number number : list) {
                  System.out.print(number + " ");
              }
              System.out.println();
          }
      
          public static void main(String[] args) {
              List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5);
              List<Double> doubleList = Arrays.asList(1.1, 2.2, 3.3);
      
              printNumbers(intList); // 输出: 1 2 3 4 5
              printNumbers(doubleList); // 输出: 1.1 2.2 3.3
          }
      }
      
    • 下限通配符 ? super T:表示可以接受类型为TT的父类。

      public class LowerBoundedWildcardExample {
          public static void addNumbers(List<? super Integer> list) {
              list.add(1);
              list.add(2);
              list.add(3);
          }
      
          public static void main(String[] args) {
              List<Number> numberList = new ArrayList<>();
              addNumbers(numberList);
              System.out.println(numberList); // 输出: [1, 2, 3]
      
              List<Object> objectList = new ArrayList<>();
              addNumbers(objectList);
              System.out.println(objectList); // 输出: [1, 2, 3]
          }
      }
      
  3. 泛型方法与类型推断

    在调用泛型方法时,编译器会根据传入的参数类型自动推断类型参数,这使得代码更简洁:

    public class GenericMethodWithInference {
        public static <T> void printElement(T element) {
            System.out.println("Element: " + element);
        }
    
        public static void main(String[] args) {
            printElement("Hello"); // 自动推断T为String
            printElement(123); // 自动推断T为Integer
            printElement(45.67); // 自动推断T为Double
        }
    }
    
  4. 泛型类型擦除

    在Java中,泛型在编译时会被擦除,这意味着在运行时所有泛型信息都会被移除。这种机制被称为类型擦除(Type Erasure)。类型擦除的主要目的是为了向后兼容Java早期版本。

    public class TypeErasureExample {
        public static void main(String[] args) {
            List<String> stringList = new ArrayList<>();
            List<Integer> intList = new ArrayList<>();
    
            System.out.println(stringList.getClass() == intList.getClass()); // 输出: true
        }
    }
    

    在这个例子中,stringListintList在运行时具有相同的类类型,即使它们的泛型类型参数不同。

四、泛型的最佳实践
  1. **使用泛型提高

代码的类型安全性**:泛型可以在编译时捕获类型错误,从而减少运行时错误。

  1. 避免不必要的类型转换:使用泛型可以减少类型转换的需要,使代码更加简洁和安全。

  2. 理解类型擦除的局限性:由于类型擦除机制,泛型在运行时不会保留类型信息,因此不能用于某些反射操作。

  3. 适当使用通配符:通配符可以提高泛型代码的灵活性,但要注意不要滥用,确保代码的可读性和维护性。

五、总结

泛型是Java中一个非常重要的特性,它通过引入类型参数,提高了代码的重用性、类型安全性和可读性。本文介绍了泛型的基本概念、使用方法和高级用法,并提供了详细的代码示例来说明这些概念。希望通过这篇文章,你能更好地理解和使用Java泛型,使你的代码更加健壮和灵活。

通过对泛型的深入理解和实践应用,你将能够编写出更加通用和安全的代码,从而提升整体的编程能力和代码质量。希望这篇文章对你有所帮助,并期待你在实际项目中成功应用这些知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1924456.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Transformer模型:Encoder的self-attention mask实现

前言 这是对Transformer模型的Word Embedding、Postion Embedding内容的续篇。 视频链接&#xff1a;19、Transformer模型Encoder原理精讲及其PyTorch逐行实现_哔哩哔哩_bilibili 文章链接&#xff1a;Transformer模型&#xff1a;WordEmbedding实现-CSDN博客 Transformer模型…

docker-compose安装PolarDB-PG数据库

文章目录 一. Mac1.1 docker-compose.yaml1.2 部署1.3 卸载4. 连接 二. Win102.1 docker-compose.yaml2.2 部署2.3 卸载 参考官方文档 基于单机文件系统部署 一. Mac 1.1 docker-compose.yaml mkdir -p /Users/wanfei/docker-compose/polardb-pg && cd /Users/wanfei…

Linux - 综合使用shell脚本,输出网站有效数据

综合示例: shell脚本实现查看网站分数 使用编辑器编辑文件jw.sh为如下内容: #!/bin/bash save_file"score" # 临时文件 semester20102 # 查分的学期, 20102代表2010年第二学期 jw_home"http://jwas3.nju.edu.cn:8080/jiaowu" # 测试网站首页地址 jw_logi…

zigbee开发工具:2、zigbee工程建立与配置

本文演示基于IAR for 8051&#xff08;版本10.10.1&#xff09;如何建立一个开发芯片cc2530的zigbee的工程&#xff0c;并配置这个工程&#xff0c;使其能够将编译的代码进行烧录&#xff0c;生成.hex文件。IAR for 8051&#xff08;版本10.10.1&#xff09;支持工程使用C语言&…

STM32智能交通灯系统教程

目录 引言环境准备智能交通灯系统基础代码实现&#xff1a;实现智能交通灯系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;交通管理与优化问题解决方案与优化收尾与总结 1. 引言 智能交通灯系统通过STM…

Python游戏开发:四连珠(内附完整代码)

四连珠&#xff08;Connect Four&#xff09;是一款经典的棋类游戏&#xff0c;由两名玩家在7列6行的网格上轮流下棋。玩家的目标是将自己的棋子在垂直、水平或对角线上连成一条线&#xff0c;通常是四个棋子。如果一方成功做到这一点&#xff0c;那么他就赢得了游戏。如果所有…

视频监控汇聚平台:通过SDK接入大华DSS视频监控平台的源代码解释和分享

目录 一、视频监控汇聚平台 1、概述 2、视频接入能力 3、视频汇聚能力 二、大华DSS平台 1、DSS平台概述 2、大华DSS平台的主要特点 &#xff08;1&#xff09;高可用性 &#xff08;2&#xff09;高可靠性 &#xff08;3&#xff09;易维护性 &#xff08;4&#xf…

《昇思25天学习打卡营第2天|02快速入门》

课程目标 这节课准备再学习下训练模型的基本流程&#xff0c;因此还是选择快速入门课程。 整体流程 整体介绍下流程&#xff1a; 数据处理构建网络模型训练模型保存模型加载模型 思路是比较清晰的&#xff0c;看来文档写的是比较连贯合理的。 数据处理 看数据也是手写体数…

【算法】平衡二叉树

难度&#xff1a;简单 题目 给定一个二叉树&#xff0c;判断它是否是 平衡二叉树 示例&#xff1a; 示例1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;true 示例2&#xff1a; 输入&#xff1a;root [1,2,2,3,3,null,null,4,4] 输出&…

炒鸡清晰的防御综合实验(内含区域划分,安全策略,用户认证,NAT认证,智能选路,域名访问)

实验拓扑图如下&#xff1a; 前面六个条件在之间的实验中做过了&#xff0c;详细步骤可以去之前的文章看 这里简写一下大致步骤 第一步&#xff1a; 先将防火墙之外的配置给配置好&#xff0c;比如&#xff0c;PC的IP,交换上的Vlan划分。 第二步&#xff1a; 在浏览器上登…

用SurfaceView实现落花动画效果

上篇文章 Android子线程真的不能刷新UI吗&#xff1f;(一&#xff09;复现异常 中可以看出子线程更新main线程创建的View&#xff0c;会抛出异常。SurfaceView不依赖main线程&#xff0c;可以直接使用自己的线程控制绘制逻辑。具体代码怎么实现了&#xff1f; 这篇文章用Surfa…

【算法专题】快速排序

1. 颜色分类 75. 颜色分类 - 力扣&#xff08;LeetCode&#xff09; 依据题意&#xff0c;我们需要把只包含0、1、2的数组划分为三个部分&#xff0c;事实上&#xff0c;在我们前面学习过的【算法专题】双指针算法-CSDN博客中&#xff0c;有一道题叫做移动零&#xff0c;题目要…

小公司的Git工作流程

项目初始化 git init并添加.gitignore文件 Git使用 通过git add . 把代码推到暂存区通过git commit -m “你的说明”&#xff0c;将暂存区的代码推到本地仓库将本地仓库的代码通过git push 推到远程仓库远程仓库(gitee/gitlab/github)同事就可以通过命令git pull将你推上去的…

信息学奥赛初赛天天练-46-CSP-J2020阅读程序2-进制转换、十进制转k进制、等比数列通项公式、等比数列求和公式应用

PDF文档公众号回复关键字:20240713 2020 CSP-J 阅读程序2 1阅读程序(程序输入不超过数组或字符串定义的范围&#xff1b;判断题正确填 √&#xff0c;错误填 。除特殊说明外&#xff0c;判断题 1.5 分&#xff0c;选择题 3 分&#xff0c;共计 40 分) 01 #include <iostre…

java各种锁介绍

在 Java 中&#xff0c;锁是用来控制多个线程对共享资源进行访问的机制。主要有以下几种类型的锁&#xff1a; 1.互斥锁&#xff08;Mutex Lock)&#xff1a;最简单的锁&#xff0c;一次只允许一个线程访问共享资源。如果一个线程获得了锁&#xff0c;其他线程必须等待锁被释放…

DEBUG:jeston卡 远程ssh编程

问题 jeston 打开网页 gpt都不方便 而且只需要敲命令就行 解决 下载MobaXterm(window执行) liunx需要虚拟机 软件 远程快速复制命令

【kubernetes】Helm包管理器基本概念与Chart实战

概念&#xff1a;基础架构与常用命令 三个重要概念&#xff1a; 1.chart 创建Kukernetes应用程序所必需的一组信息。 2.config 包含了可以合并到打包的chart中的配置信息&#xff0c;用于创建一个可发布的对象。 3.release 是一个与特走配置相结合的chart的运行实例。 常用命…

聊点基础---Java和.NET开发技术异同全方位分析

1. C#语言基础 1.1 C#语法概览 欢迎来到C#的世界&#xff01;对于刚从Java转过来的开发者来说&#xff0c;你会发现C#和Java有很多相似之处&#xff0c;但C#也有其独特的魅力和强大之处。让我们一起来探索C#的基本语法&#xff0c;并比较一下与Java的异同。 程序结构 C#程序…

数学建模·非线性规划

整型规划 适用于一个变量或多个变量的值只能是整型的情况 整形规划的分类 0-1背包问题 对于一个物品来说&#xff0c;只有选和不选两种情况 表现为单下标&#xff0c;单变量问题 例&#xff1a;建设学校问题 对于每个学校来说只有选和不选两种情况&#xff0c;在数学上我们用…

O型密封圈橡胶制品外观视觉检测解决方案

一;O型密封圈橡胶制品行业背景调查 O型密封圈橡胶制品的外观视觉检测是一个确保产品质量和性能的关键步骤。以下是对该检测过程的详细分析和归纳&#xff1a; 一&#xff1a;检测目的 确保O型密封圈橡胶制品在生产过程中无缺陷&#xff0c;如杂质、毛刺、尺寸不符等。 满足不同…