1470 字
7 分钟

泛型

2026-03-11
浏览量 加载中...

泛型#

一、 泛型的引入与好处#

1.1 传统方法的问题#

在集合中,使用传统方法(不使用泛型)存在两个主要问题:

  1. 类型不安全:不能对加入到集合中的数据类型进行约束,可以添加任意类型的对象。
  2. 效率低​:遍历时,需要进行频繁的类型转换(Object -> 具体类型),数据量大时影响效率。

1.2 泛型的好处#

使用泛型可以解决上述问题:

  1. 类型安全:在编译时检查添加元素的类型,不符合则报错,提高了安全性。

  2. 提高效率:减少了遍历时不必要的类型转换次数。

    • 不使用泛型:Dog -> Object (存入) -> Dog (取出,需强转)
    • 使用泛型:Dog -> Dog (存入) -> Dog (取出,无需强转)
  3. 消除警告:代码更加简洁、健壮,不再有编译警告。

二、 泛型介绍#

2.1 基本概念#

  • 泛型​:又称​参数化类型,是 JDK 5.0 引入的新特性。
  • 核心思想:在类声明或实例化时,通过一个标识符来指定操作的数据类型。
  • 作用:可以在类声明时,用一个标识符表示类中某个属性的类型、某个方法的返回值类型或参数类型。
  • 优点:保证如果程序在编译时没有发出警告,运行时就不会产生 ClassCastException 异常。

三、 泛型语法与使用#

3.1 泛型的声明与实例化#

  • 声明​:在类名或接口名后使用尖括号 <> 定义泛型标识符,如 class Person<E>, interface List<T>。
  • 实例化​:在创建对象时,在尖括号 <> 中指定具体的类型。
// 声明一个泛型类
class Person<E> { ... }
// 实例化,指定 E 为 String 类型
Person<String> person = new Person<String>("韩顺平教育");

3.2 泛型使用的注意事项和细节#

  1. 类型限制​:泛型标识符 T, E 等​只能是引用类型,不能是基本数据类型。
List<Integer> list1 = new ArrayList<Integer>(); // OK
// List<int> list2 = new ArrayList<int>(); // 错误
  1. 继承关系​:在给泛型指定具体类型后,可以传入该类型或其​子类类型
  2. 使用形式
// 完整写法
ArrayList<Integer> list1 = new ArrayList<Integer>();
// 简化写法(类型推断),推荐使用
ArrayList<Integer> list2 = new ArrayList<>();
// 未指定泛型,默认为 Object
ArrayList list3 = new ArrayList(); // 等价于 ArrayList<Object> list3 = ...

四、 自定义泛型#

4.1 自定义泛型类#

  • 基本语法​:class 类名<T, R…> { … }

|500

  • 注意细节

    1. 普通成员(属性、方法)可以使用泛型。
    2. 不能初始化使用泛型的数组(因为 new 时无法确定 T 的具体类型)。
    3. 静态成员(属性、方法)中不能使用类的泛型(因为静态成员在类加载时初始化,而泛型类型在创建对象时才确定)。
    4. 泛型类的类型,是在创建对象时确定的。
    5. 如果在创建对象时没有指定类型,则默认为 Object。

4.2 自定义泛型接口#

  • 基本语法​:interface 接口名<T, R…> { … }

  • 注意细节

    1. 接口中,静态成员也不能使用泛型(同泛型类)。
    2. 泛型接口的类型,在继承接口实现接口时确定。
    3. 没有指定类型,默认为 Object。

4.3 自定义泛型方法#

  • 基本语法​:修饰符 <T, R…> 返回类型 方法名(参数列表) { … }

  • 注意细节

    1. 泛型方法可以定义在普通类中,也可以定义在泛型类中。
    2. 当泛型方法被调用时,类型会确定。
    3. public void eat(E e) {} 这样的方法,其泛型 E 依赖于类定义的泛型,不是泛型方法。
    4. public <T> void fly(T t) {} 这样的方法,其泛型 T 独立于类,是泛型方法。

五、 泛型的继承和通配符#

5.1 泛型没有继承性#

  • 虽然 String 是 Object 的子类,但 List<String> 并不是 List<Object> 的子类。它们是并列关系,没有继承关系。

5.2 泛型通配符#

为了表示泛型之间的某种关系,引入了通配符 ?。

  1. <?>:无界通配符

    • 表示可以接受任意的泛型类型。
    • List<?> 是 List<String>, List<Object> 等各种泛型 List 的父类。
    • 注意​:不能向 List<?> 中添加除 null 以外的任何元素(因为类型不确定),但可以读取,读取出的类型是 Object。
  2. <? extends A>:上界通配符

    • 表示可以接受 ​A 类以及 A 类的子类(不限于直接子类)。
    • 规定了泛型的​上限
    • 同样,不能向 List<? extends A> 中添加除 null 以外的任何元素(因为无法确定具体是哪个子类),但可以读取,读取出的类型是 A。
  3. <? super A>:下界通配符

    • 表示可以接受 ​A 类以及 A 类的父类(不限于直接父类)。
    • 规定了泛型的​下限
    • 可以向 List<? super A> 中添加 A 及其子类对象(因为父类引用可以指向子类对象)。
    • 读取时,返回的类型是 Object。

六、 JUnit 单元测试(补充)#

6.1 为什么需要 JUnit#

  • 传统测试需要将代码写入 main 方法,测试多个功能时需要来回注销、切换,非常麻烦。
  • JUnit 可以直接运行一个方法进行测试,并给出相关信息,方便快捷。

6.2 基本介绍#

  • JUnit 是一个 Java 语言的单元测试框架。
  • 多数 Java 开发环境(如 IDEA)都已集成 JUnit 作为单元测试工具。

6.3 使用步骤(简述)#

  1. 在需要测试的类中,导入 JUnit 相关包(通常由 IDE 自动完成)。
  2. 在需要测试的方法上添加 @Test 注解。
  3. 在方法体内编写测试代码。
  4. 右键点击方法名或类名,选择 Run ‘方法名()’ 或 Run ‘类名’ 执行测试。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
泛型
https://blog.tsh520.cn/posts/java笔记本/泛型/
作者
团子和蛋糕
发布于
2026-03-11
许可协议
CC BY-NC-SA 4.0

评论区

Profile Image of the Author
团子和蛋糕
团子喜欢吃蛋糕!
公告
如果你喜欢,那么欢迎来到我的世界!
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
23
分类
7
标签
14
总字数
85,228
运行时长
0
最后活动
0 天前

目录