java 泛型是 JDK5 引入的参数化类型机制,把类型当成参数传递,在编译阶段做类型校验,避免强制类型转换,解决集合存储任意 Object 带来的类型不安全问题,泛型只在编译期生效,运行期会发生类型擦除。之所以引入泛型,是早期集合可以存入任意类型对象,取出的时候默认是 Object,必须手动强转,一旦存入类型不一致,运行时就会抛出类型转换异常,泛型就是在编译阶段提前锁定元素类型,把类型错误提前暴露,提升代码安全性和可读性。学习的时候一般先理解参数化类型这个核心概念,然后学习泛型类、泛型方法、泛型接口三种写法,接着掌握通配符?、上界 extends、下界 super,之后理解类型擦除底层原理,最后掌握泛型常见限制和面试考点,每一种写法都配合集合 List、Map 代码实操验证。掌握之后就可以看懂 Spring、MyBatis 大量泛型代码,也能应对泛型相关笔试面试题。
一 泛型核心作用
清单
1 编译期类型检查,提前发现类型错误,减少运行时 ClassCastException
2 省去大量强制类型转换代码,代码更简洁
3 实现通用代码复用,同一份类或者方法可以适配多种数据类型
4 提升代码可读性,一眼看出集合里面存放的是什么类型
二 泛型三种基本形式
表格
| 类型 | 语法说明 | 典型例子 |
|---|---|---|
| 泛型类 | 在类名后面加 | class MyList |
| 泛型方法 | 方法返回值前面声明 | public |
| 泛型接口 | 接口名后面加 | interface Dao |
三 类型参数命名规范
清单
1 T Type 代表通用类型
2 E Element 集合元素,List
3 K Key Map 键
4 V Value Map 值
5 R Return 返回值类型
6 字母只是约定,也可以自定义其他字母,但是行业统一推荐上面这套命名
四 通配符与上下界(重点难点)
清单
1 无界通配符?代表未知类型,可以接收任意泛型类型,但是不能添加元素
2 上界通配符?extends T 可以接收 T 以及 T 的子类,适合读取数据,不能添加元素
3 下界通配符?super T 可以接收 T 以及 T 的父类,适合写入数据,读取只能当成 Object
4 记忆口诀 PECS producer extends consumer super,生产者用 extends,消费者用 super
五 类型擦除(底层核心原理)
清单
1 泛型信息只存在编译阶段,编译成字节码之后,泛型类型参数会被擦除
2 擦除之后,无界泛型 T 会替换成 Object,有上界 extends Number 会替换成 Number
3 运行期无法通过反射获取真实泛型参数,数组泛型会受到限制
4 类型擦除是 java 泛型和 C++ 模板最大区别,C++ 模板运行期会生成不同类型代码
六 泛型使用限制(高频考点)
清单
1 不能基本数据类型作为泛型参数,只能使用包装类,比如 List
2 不能 new T (),不能创建泛型类型实例
3 不能创建泛型数组 new T [] 会受限
4 静态方法不能直接使用类上声明的泛型参数
5 不能使用基本类型,不能抛泛型类型异常
6 泛型重载容易混淆,擦除之后方法签名相同会编译报错
七 泛型在集合中的应用
清单
1 List
2 Map
3 没有泛型的原始类型 Raw Type,虽然可以编译,但是会丢失类型检查,属于不推荐写法
八 常见误区
清单
1 误以为 List
2 误以为运行时还保留泛型类型,运行期已经擦除
3 混淆泛型方法和泛型类,泛型方法的
【常见问题】
问题 1 java 泛型类型擦除是什么意思
回答 1 java 泛型类型擦除是指泛型只在编译期生效,编译成 class 字节码之后泛型参数会被替换成上界或者 Object,运行阶段不再保留泛型类型信息,这是 java 泛型非常核心底层原理。
问题 2 java 泛型为什么不能使用基本数据类型
回答 1 java 泛型参数必须是引用类型,基本数据类型 int double 不属于类,所以泛型不能直接写 List
问题 3 PECS 原则在 java 泛型里面是什么
回答 1 PECS 是 java 泛型通配符核心原则,producer extends 生产者读取数据使用?extends T,consumer super 消费者写入数据使用?super T,是开发和面试经常考察知识点。
问题 4 List
回答 1 List
【免责申明】
本文内容为 java 泛型基础知识讲解,泛型属于 JDK5 之后特性,不同 JDK 版本表现一致,业务开发和面试可以参考,内容仅作为学习参考。


