Generics
Java 泛型(Generics)是 Java 编程语言中引入的一种严格的类型参数化机制,旨在增强编译时类型检查并消除显式类型转换的需求。其核心特性与设计目标如下:
1. 类型安全(Type Safety)
- 泛型通过在编译时强制类型约束,确保集合类(如
List<T>
、Map<K,V>
)仅能操作指定类型的元素。例如:List<String> list = new ArrayList<>();
list.add("text"); // 合法
list.add(123); // 编译错误 - 此举有效避免了运行时因类型不匹配引发的
ClassCastException
。
2. 编译时类型擦除(Type Erasure)
- 泛型信息仅存在于编译阶段,运行时通过类型擦除(Type Erasure)机制转换为原生类型(Raw Types)。例如
List<String>
在运行时表现为List
。 - 擦除后,编译器自动插入类型转换指令,确保与遗留代码的二进制兼容性。
3. 参数化类型(Parameterized Types)
- 允许类、接口及方法声明类型参数(如
T
、K
、V
),用户使用时指定具体类型:public class Box<T> {
private T content;
public void set(T content) { this.content = content; }
public T get() { return content; }
} - 实例化时绑定具体类型:
Box<Integer> intBox = new Box<>();
4. 通配符与边界(Wildcards & Bounds)
- 通配符
?
:表示未知类型,如List<?>
可接受任意类型的List
。 - 边界约束:
<? extends T>
:上界通配符(协变),接受T
或其子类。<? super T>
:下界通配符(逆变),接受T
或其父类。- 例如:
void process(List<? extends Number> numbers) { ... } // 允许 List<Integer>, List<Double>
void append(List<? super Integer> list) { ... } // 允许 List<Number>, List<Object>
5. 泛型方法(Generic Methods)
- 独立于类泛型参数的方法级泛型:
public static <T> T firstElement(List<T> list) {
return list.isEmpty() ? null : list.get(0);
} - 类型推断可省略显式声明:
String first = firstElement(stringList);
设计意义
- 代码复用:通过抽象类型参数实现算法与数据结构的通用性。
- 文档化:类型参数显式声明了类或方法的预期类型,提升代码可读性。
- 错误前置:将潜在的类型错误暴露于编译期而非运行时。
注意事项
- 泛型类型不可为基本数据类型(需使用包装类,如
Integer
替代int
)。 - 受类型擦除影响,运行时无法获取泛型的具体类型信息(如
T.class
非法)。
综上,Java 泛型通过编译时类型检查与擦除机制,在保持语言简洁性的同时提供了强大的类型抽象能力,是 Java 类型系统的重要组成。