跳到主要内容

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)

  • 允许类、接口及方法声明类型参数(如 TKV),用户使用时指定具体类型:
    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 类型系统的重要组成。