类型擦除指Java在编译期移除泛型信息,运行时无法获取真实泛型类型。例如List被擦除为List,导致不能使用instanceof List、无法创建泛型数组、方法重载受限等问题。为支持多态,编译器生成桥接方法,如继承ArrayList时自动生成add(Object)调用add(String)。尽管类型被擦除,仍可通过反射获取类、字段或方法声明中的泛型信息,如getGenericSuperclass()、getGenericType()等,但局部变量的泛型完全消失。该机制保证了泛型与旧版本兼容,但也带来一定限制。

Java中的类型擦除机制是泛型实现的核心特性之一,它意味着泛型信息在编译阶段被移除,运行时无法获取真实的泛型类型。理解这一点对正确使用泛型、避免常见错误非常重要。
什么是类型擦除
Java的泛型是在编译期生效的,编译器会检查类型安全,并将泛型信息“擦除”,替换成原始类型(通常是Object或泛型的上界)。这意味着JVM运行时并不知道你使用的具体泛型类型。
例如:
List经过编译后,等价于:
立即学习“Java免费学习笔记(深入)”;
List list = new ArrayList();String这个类型信息被擦除了,只保留了原始类型List。
类型擦除带来的影响
由于类型在运行时不可见,以下情况需要注意:
-
不能通过泛型类型做 instanceof 判断:比如 if (obj instanceof List
) 是非法的,只能写成 if (obj instanceof List)。 - 无法创建泛型数组:像 new T[] 这样的代码不被允许,因为类型T在运行时不存在。
- 方法重载受限:下面两个方法不能共存,因为擦除后都是接收List参数:
void method(List
桥接方法与多态支持
为了在类型擦除后仍能支持多态,编译器会自动生成“桥接方法”(bridge method)。
例如,当你继承一个泛型类并指定具体类型时:
class MyList extends ArrayList@Override
public void add(String s) { ... }
}
编译器会生成一个桥接方法:
public void add(Object obj) {add((String) obj); // 调用真正的 add(String)
}
这样确保了多态调用的正确性,即使底层类型被擦除。
如何获取泛型类型信息
虽然类型被擦除,但在某些情况下仍能通过反射获取泛型信息:
- 通过 Class.getGenericSuperclass() 获取父类的泛型类型。
- 通过 Field.getGenericType() 获取字段声明的泛型类型。
- 通过 Method.getGenericParameterTypes() 获取方法参数的泛型类型。
这些信息存在于字节码中,但仅限于声明位置,局部变量的泛型信息完全被擦除。
基本上就这些。类型擦除让Java的泛型向后兼容,但也带来了一些限制。理解它有助于写出更安全、正确的泛型代码。










