Java泛型完整笔记
一、泛型基础
泛型:参数化类型,把类型作为参数。
- 作用:编译期做类型检查,避免强制类型转换,防止
ClassCastException - 特点:只在编译期生效,运行时做类型擦除,字节码中泛型信息消失。
常用占位符:
TType 类型EElement 元素KKey 键VValue 值?通配符
1.泛型类
语法:public class 类名<T> {}
java
public class Result<T> {
private int code;
private String msg;
private T data;
// get、set
}
使用:
java
Result<User> r1 = new Result<>(); // JDK7钻石语法,右侧自动推导类型
要点:
<T>写在类名后,整个类内部可用T- 静态方法不能使用类定义的泛型T
- 不能
new T()、不能直接创建T[]数组 - 泛型类也可以是JavaBean;普通JavaBean所有字段类型固定,泛型类部分字段类型占位可变。
2.泛型方法
<E>写在方法返回值类型前面,属于方法本身,和类泛型无关。
java
public <E> E method(E e){
return e;
}
类不是泛型类,也可以定义泛型方法;调用时编译器自动推导类型。
二、泛型没有继承性,对象(数据)具备继承性 ✨重点
- 对象/数据有继承性(多态成立)
java
// meiduan extends animals
animals a = new meiduan("tom",1); // ✅子类对象赋值给父类引用
- 泛型不具备继承性 虽然
meiduan是animals子类,但是ArrayList<meiduan>不是ArrayList<animals>的子类。
java
ArrayList<animals> list = new ArrayList<meiduan>(); // ❌编译报错
泛型参数不同,集合类型之间不存在父子关系。
想要方法接收多种泛型集合,使用通配符。
三、通配符 ?
① ? 无边界通配符 List<?>
可以接收任意类型集合;只能读取,不能add添加元素。
② 上界通配符 ? extends 父类
java
List<? extends animals>
- 可以接收:
List<animals>、List<bosi>、List<meiduan> - ✅ 可以读取元素,拿到父类类型
- ❌ 不能add添加元素
- 使用场景:只读取遍历数据
java
public static void keepPet(List<? extends animals> list){
for(animals c : list){
c.eat();
}
}
③ 下界通配符 ? super 子类
java
List<? super animals>
- ✅ 可以存入子类对象
- ❌ 读取出来只能是Object,拿不到父类
- 使用场景:主要往集合存数据
记忆口诀
? extends:读,不能存? super:存,读出Object?:任意集合,不能存
四、类型擦除(面试)
- 泛型只存在编译期,运行时泛型信息被擦除。
- 无边界
<T>擦除为Object;<T extends Animal>擦除为Animal。 List<String>、List<Integer>运行时是同一个List.class。List<Object>和List<String>没有父子关系,不能互相赋值;需要用通配符List<?>。
五、泛型使用场景
- 集合框架:
List<E>、Map<K,V>,约束元素类型,避免强转异常。 - 通用包装类:如
Result<T>,一套类适配多种数据,不用重复写多个JavaBean。 - 通用工具方法:泛型方法实现一套方法处理多种类型。
- 方法形参:通配符,接收多种子类集合。
六、高频错误
- 类泛型不能用在静态方法。
java
class A<T>{
public static void test(T t){} //❌
}
- 不能
new T()、不能直接创建泛型数组new T[]。 - main方法不能写泛型:
public static <T> void main()错误。 ArrayList<父类>不能接收ArrayList<子类>,泛型无继承;改用通配符? extends。List<? extends 父类>不能add元素。
七、泛型类 vs 普通JavaBean
| 对比项 | 普通JavaBean | 泛型类 |
|---|---|---|
| 属性类型 | 全部固定写死 | 部分属性<T>占位,使用时确定真实类型 |
| 代码复用 | 业务类型改变,需要新建Bean | 一套类,传入不同类型复用 |
| 典型用途 | 业务实体(User、Order) | 容器、返回值包装、工具封装 |
JavaBean是编码规范,泛型是语法特性;泛型类也可以是JavaBean。
八、背诵简答题
- 泛型作用:编译期类型检查,减少强制类型转换,避免运行类型转换异常。
- 泛型没有继承性:子类对象可以赋值父类引用;但是
ArrayList<子类>不是ArrayList<父类>的子类。 - 通配符:
? extends可读不可存;? super可存,读取只能Object。 - 类型擦除:运行时去掉泛型信息,替换为Object或者上界父类。
- 类上定义的泛型,静态方法不能使用。
九、经典考题
java
animals an = new meiduan("tom",1); //✅ 对象多态,数据具备继承性
ArrayList<animals> list = new ArrayList<meiduan>(); //❌泛型无继承
List<? extends animals> list2 = new ArrayList<meiduan>(); //✅通配符