Java 的泛型是如何工作的 ? 什么是类型擦除 ?
参考回答
Java 的泛型通过在编译时提供类型检查和保证类型安全来工作。在运行时,由于 Java 的泛型实现采用了 类型擦除,泛型信息会被移除,所有泛型类型最终都会被替换为原生类型(如 Object
或具体的边界类型)。类型擦除是为了兼容 Java 的旧版本(JDK 1.4 及之前),那些版本没有泛型支持。
详细讲解与拓展
1. 泛型是如何工作的
泛型允许你在类、接口和方法中定义类型参数,以便重用代码并确保类型安全。以下是泛型的几个关键点:
- 编译时检查:泛型会在编译时检查类型是否匹配,避免了运行时出现
ClassCastException
。 - 类型参数:使用尖括号
<T>
定义类型参数。泛型类、方法或接口可以适配多种类型。 - 工作原理:编译器根据泛型代码生成类型安全的原生代码,然后通过 类型擦除 在运行时将泛型类型替换为它的边界(或
Object
)。
示例代码:
在上面的例子中,Box
是一个泛型类,可以存储任意类型的值。<T>
是类型参数,使用时会替换为具体的类型(如 String
)。
2. 什么是类型擦除
类型擦除是指 Java 的泛型只存在于编译期,编译后会将泛型类型擦除,转变为原生类型(raw type),以兼容旧版本的 JVM。
类型擦除的规则:
- 无边界泛型:泛型类型会被替换为
Object
。 - 有边界泛型:如果定义了泛型边界(
<T extends Number>
),类型擦除时会替换为边界类型。 - 桥接方法:在泛型类中,子类与父类方法签名可能不一致,编译器会生成桥接方法以保证兼容性。
示例:
编译后,泛型方法 add(T, T)
会被转换为:
3. 类型擦除的限制
由于类型擦除的存在,Java 泛型在运行时有以下局限性:
- 不能使用泛型类型创建实例:
- 无法检测运行时类型: 泛型类型的实际参数在运行时不可用。
- 不能创建泛型数组:
- 类型冲突: 方法签名可能因为类型擦除而发生冲突。
4. 泛型的拓展知识
- 通配符(Wildcard): 泛型中可以使用通配符
?
表示不确定的类型。常用的通配符有:? extends T
:表示该类型是T
的子类或T
本身。? super T
:表示该类型是T
的父类或T
本身。?
:表示不确定的类型。
示例:
- 泛型方法: 可以在方法中单独声明泛型类型。
- 泛型擦除的绕过方式:
- 使用反射获取泛型类型:
总结
- 泛型的优点:编译时类型检查、提高代码重用性。
- 类型擦除的影响:导致一些运行时局限性(如无法检测泛型类型、泛型数组不能直接创建)。
- 实际开发建议:尽量使用泛型的能力,尤其是集合类(如
List
和Map
),以提高代码的可读性和安全性。