### Java泛型教程 #### 1. 引言 Java Development Kit (JDK) 1.5 版本引入了对 Java 编程语言的几项扩展,其中一项就是引入了泛型(Generics)。本教程旨在介绍 Java 泛型的基础知识。如果你熟悉其他语言中的类似构造(例如 C++ 模板),你会很快发现它们之间既有相似之处也有重要的差异。如果你之前没有接触过类似概念,那么可以从头开始学习,避免误解。 #### 2. 定义简单的泛型 在 Java 中,泛型允许程序员编写类型无关的代码。最典型的例子是容器类型,如 `Collection` 层次结构中的各种类。下面是一个简单的使用示例: ```java List myIntList = new LinkedList(); // 1 myIntList.add(new Integer(0)); // 2 Integer x = (Integer) myIntList.iterator().next(); // 3 ``` 在线 3 中的强制类型转换稍微有些麻烦。通常情况下,程序员知道某个列表中存储的是哪种类型的数据。然而,强制类型转换是必要的,因为编译器只能保证迭代器返回的对象是 `Object` 类型。为了确保将结果赋值给 `Integer` 类型变量的安全性,必须进行强制类型转换。 当然,这种类型转换不仅增加了代码的复杂度,还可能引入运行时错误,尤其是当程序员误判数据类型时。 如果程序员能够明确表达自己的意图,并标记列表只包含特定的数据类型,这正是泛型的核心思想。以下是使用泛型改写上述代码片段的例子: ```java List<Integer> myIntList = new LinkedList<Integer>(); // 1' myIntList.add(new Integer(0)); // 2' Integer x = myIntList.iterator().next(); // 3' ``` #### 3. 泛型与子类型 在 Java 中,泛型类型遵循特定的子类型规则。例如,`List<String>` 并不是 `List<Object>` 的子类型。这意味着不能将 `List<String>` 的引用赋值给 `List<Object>` 类型的变量。这是为了确保类型安全,避免运行时的类型错误。 #### 4. 通配符 通配符(wildcards)是用来表示未知类型的占位符。它们使得可以在不知道具体类型的情况下操作泛型类型。例如: ```java List<?> unknownList = new LinkedList<String>(); ``` 这里 `?` 表示未知类型,可以是任何类型。这样就可以处理不确定类型的列表,但不允许添加元素到这个列表中,因为不清楚列表中存储的是什么类型。 ##### 4.1 有界通配符 有界通配符允许指定一个或多个类型边界。例如: ```java List<? extends Number> numberList = new LinkedList<Integer>(); ``` 这里的 `? extends Number` 表示列表中的元素必须是 `Number` 或其子类型。同样地,可以使用 `? super T` 来表示列表中的元素必须是类型 `T` 或其父类型。 #### 5. 泛型方法 除了定义泛型类之外,Java 还支持泛型方法。这些方法可以在非泛型类中定义,并且可以接受泛型参数。例如: ```java public class Example { public <T> void print(T t) { System.out.println(t); } } ``` 这里 `<T>` 是泛型参数声明,`T` 可以代表任何类型。 #### 6. 与遗留代码的交互 ##### 6.1 在泛型代码中使用遗留代码 在使用泛型时,有时需要与不支持泛型的遗留代码进行交互。例如,假设有一个不带泛型类型的列表: ```java List list = new ArrayList(); // ... add some elements ... List<String> stringList = (List<String>) list; ``` 这里需要进行显式类型转换,但这可能导致运行时异常。为了避免这种情况,可以使用通配符或者泛型方法来安全地操作这些列表。 ##### 6.2 抹除与转换 在运行时,所有泛型信息都会被抹除(erasure)。这意味着在运行时无法区分 `List<String>` 和 `List<Integer>`。这导致了泛型代码与非泛型代码之间的兼容性问题。Java 使用了一种称为“类型擦除”的技术,它将泛型类型转换为非泛型类型,并通过类型检查来确保类型安全。 ##### 6.3 在遗留代码中使用泛型代码 在遗留代码中使用泛型代码时,需要注意类型擦除可能导致的一些问题。例如,当你从一个泛型方法返回一个泛型类型时,该类型会被擦除为对应的原始类型。这可能会导致类型不匹配的问题。 #### 7. 细节问题 ##### 7.1 泛型类由所有调用共享 Java 泛型的一个重要特点是:每个泛型类实例实际上都是相同的类的实例,只是在编译时根据不同的类型参数进行了类型检查。这意味着不同类型的泛型实例实际上是同一个类的不同实例。 ##### 7.2 类型转换和 `instanceof` 使用泛型时,需要特别注意类型转换和 `instanceof` 操作符的行为。例如,当使用 `instanceof` 检查泛型类型的实例时,由于类型擦除,实际检查的是对应的原始类型。 ##### 7.3 数组 Java 泛型的一个限制是不能创建泛型数组。这是因为泛型类型在运行时被擦除,而创建数组需要具体的类型信息。 #### 8. 类文字作为运行时类型令牌 在 Java 中,可以使用类文字(class literals)来获取运行时的类型信息。这对于泛型类型尤其有用,因为类型擦除使得无法通过常规方式获取泛型类型的信息。例如: ```java Class<?> type = String.class; ``` #### 9. 更多关于通配符的乐趣 通配符提供了许多强大的功能,包括有界通配符和通配符捕获等高级特性。 ##### 9.1 通配符捕获 通配符捕获是一种机制,用于处理带有通配符的方法签名。例如,在方法签名中使用通配符时,Java 编译器会自动推断出合适的类型。 #### 10. 将遗留代码转换为使用泛型 将现有代码迁移到使用泛型时,需要注意以下几个关键点: - **逐步迁移**:从简单的类开始,逐渐过渡到更复杂的类。 - **测试**:在每个阶段都要进行彻底的测试,确保代码仍然按预期工作。 - **类型擦除的影响**:了解类型擦除如何影响代码,特别是与泛型相关的类型转换和检查。 #### 11. 致谢 感谢所有为 Java 泛型设计和发展做出贡献的人们,他们的努力使得 Java 成为一种更加健壮和灵活的编程语言。
![application/octet-stream](https://img-home.csdnimg.cn/images/20210720083646.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![application/x-rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![application/octet-stream](https://img-home.csdnimg.cn/images/20210720083646.png)
![chm](https://img-home.csdnimg.cn/images/20210720083646.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![zip](https://img-home.csdnimg.cn/images/20210720083736.png)
![pdf](https://img-home.csdnimg.cn/images/20210720083512.png)
![avatar-default](https://csdnimg.cn/release/downloadcmsfe/public/img/lazyLogo2.1882d7f4.png)
![avatar](https://profile-avatar.csdnimg.cn/2852e020232e4a798ad8d7336aeaeb4b_mackie.jpg!1)
- 粉丝: 0
- 资源: 4
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助
![voice](https://csdnimg.cn/release/downloadcmsfe/public/img/voice.245cc511.png)
![center-task](https://csdnimg.cn/release/downloadcmsfe/public/img/center-task.c2eda91a.png)
最新资源
- stm32C8T6 驱动mpu6050 网上代码扒下来的,自己又改了一部分希望有帮助 实测通过
- 基于多目标遗传算法的分布式电源选址定容研究 关键词:分布式电源 选址定容 多目标遗传算法 参考文档:《店主自写文档》基本复
- 基于CNN、RNN、SVM分别实现心电图分类识别python源码
- “丢失 api-ms-win-crt-runtime-l1-1-0.dll” “找不到MSVCR100.dll等等”等错误
- 基于单片STM32的mp3解码器wav播放器
- 160001-2-12-1222.nda
- openGauss 的Java驱动
- 如何在Java中实现多重继承
- VB获取CPU内存占用率及网卡流量监控
- java类和接口有什么区别
![feedback](https://img-home.csdnimg.cn/images/20220527035711.png)
![feedback-tip](https://img-home.csdnimg.cn/images/20220527035111.png)
![dialog-icon](https://csdnimg.cn/release/downloadcmsfe/public/img/green-success.6a4acb44.png)