全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-10 8 分钟 ✍️ juanwangdev

类型擦除

Java 泛型通过类型擦除实现,泛型信息在编译时被擦除。

类型擦除原理

编译前

Java
public class Box<T> {
    private T value;

    public void set(T value) { this.value = value; }
    public T get() { return value; }
}

Box<String> box = new Box<>();
box.set("Hello");
String s = box.get();

编译后(擦除)

Java
public class Box {
    private Object value;  // T 擦除为 Object

    public void set(Object value) { this.value = value; }
    public Object get() { return value; }
}

Box box = new Box();
box.set("Hello");
String s = (String) box.get();  // 编译器插入转型

类型擦除规则:无界类型参数 <T> 擦除为 Object,有界 <T extends Number> 擦除为 Number。

擦除规则

泛型声明擦除后类型
<T>Object
<T extends Number>Number
<T extends Comparable<T>>Comparable
多个边界 <T extends A & B>第一个边界 A

类型擦除验证

Java
List<String> strings = new ArrayList<>();
List<Integer> integers = new ArrayList<>();

// 运行时两者类型相同
System.out.println(strings.getClass());    // ArrayList
System.out.println(integers.getClass());   // ArrayList
System.out.println(strings.getClass() == integers.getClass());  // true

运行时无泛型信息:泛型类型在运行时被擦除,ArrayList 和 ArrayList 运行时都是 ArrayList。

类型擦除的影响

不能创建泛型数组

Java
// 错误:不能创建泛型数组
List<String>[] array = new List<String>[10];  // 编译错误

// 原因:类型擦除后无法保证类型安全
// 擦除后 List<String>[] → List[],可放入 List<Integer>

不能创建泛型实例

Java
// 错误:不能 new T()
public class Box<T> {
    public T create() {
        return new T();  // 编译错误
    }
}

// 解决:传入 Class 或 Supplier
public T create(Class<T> clazz) throws Exception {
    return clazz.newInstance();
}

不能使用基本类型

Java
// 错误:泛型不支持基本类型
List<int> list = new ArrayList<int>();  // 编译错误

// 正确:使用包装类
List<Integer> list = new ArrayList<>();

静态成员不能使用类泛型参数

Java
public class Box<T> {
    private static T value;  // 错误:静态成员不能用 T

    public static void method(T item) {}  // 错误

    // 正确:静态方法可定义自己的泛型参数
    public static <E> void method(E item) {}
}

获取泛型信息

虽然运行时擦除,但可通过反射获取部分泛型信息:

Java
public class MyClass {
    private List<String> field;
}

// 获取字段的泛型类型
Field field = MyClass.class.getDeclaredField("field");
Type genericType = field.getGenericType();

if (genericType instanceof ParameterizedType) {
    ParameterizedType pt = (ParameterizedType) genericType;
    Type[] actualTypes = pt.getActualTypeArguments();
    System.out.println(actualTypes[0]);  // String.class
}

Signature 属性:编译器在字节码中保留泛型签名信息,反射可通过 Signature 获取。

桥方法

类型擦除后,编译器生成桥方法保证多态:

Java
public class StringBox extends Box<String> {
    @Override
    public void set(String value) { ... }
    @Override
    public String get() { ... }
}

// 编译器生成桥方法
public void set(Object value) { set((String) value); }  // 桥方法
public Object get() { return get(); }  // 桥方法

要点总结

  • Java 泛型通过类型擦除实现
  • 无界 <T> 擦除为 Object,有界擦除为边界类型
  • 运行时 ArrayList 和 ArrayList 类型相同
  • 不能创建泛型数组、泛型实例
  • 泛型不支持基本类型,需用包装类
  • 静态成员不能使用类泛型参数
  • 反射可通过 Signature 获取部分泛型信息
  • 桥方法保证多态正确工作

📝 发现内容有误?点击此处直接编辑

← 上一篇 泛型类
下一篇 → 类型通配符
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库