泛型(Generics)就是“类型参数化”。
通俗讲,就是把类型当作参数来传递。平时我们定义方法时,传的是“值”参数(比如 int a);而泛型允许我们在定义类/方法时,传的是“类型”参数(比如 <T>)。
- 类型安全(编译期检查)
- 消除强制转换(代码更优雅)
- 复用代码(通用性)
通过使用泛型,程序员可以实现通用算法,这些算法可以处理不同类型的集合,可以自定义,并且类型安全且易于阅读。
类型擦除#
Java 的泛型是“伪泛型”,是通过“类型擦除(Type Erasure)”实现的。
泛型信息只在编译阶段存在。编译成 .class 字节码后,泛型类型会被替换为原始的裸类型(Raw Type)。
- 如果没有指定边界(如
<T>),擦除后变成Object。 - 如果指定了边界(如
<T extends Number>),擦除后变成Number。
2. 擦除带来的两个经典面试陷阱#
- 陷阱一:
List<String>和List<Integer>是同一个类吗?- 是的。在 JVM 眼里,它们都是
ArrayList.class,getClass()返回的结果完全相同。
- 是的。在 JVM 眼里,它们都是
- 陷阱二:能通过反射往
List<Integer>里加字符串吗?- 能! 因为运行时没有泛型约束。利用反射绕过编译期检查,完全可以存入
String,但取出来时因为编译器插入了强转(Integer),会抛出ClassCastException
- 能! 因为运行时没有泛型约束。利用反射绕过编译期检查,完全可以存入
