在Java中,泛型擦除是编译器的一种机制,它在编译阶段移除泛型类型的信息。这意味着在运行时,泛型类型的信息不会被保留。
原理
泛型擦除的基本原理是:所有的泛型类型信息都会在编译时被移除,并被其边界(或Object,如果没有指定边界)替换。因此,泛型类型不会在运行时存在。
例子
考虑以下泛型类:
public class Box<T> {
private T value;
public Box(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
在编译过程中,这个类会被转换成:
public class Box {
private Object value;
public Box(Object value) {
this.value = value;
}
public Object getValue() {
return value;
}
public void setValue(Object value) {
this.value = value;
}
}
边界
如果泛型类型有边界,例如T extends Number
,那么在擦除后,类型将被其上界替换:
public class Box<T extends Number> {
private T value;
public Box(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
会被转换成:
public class Box {
private Number value;
public Box(Number value) {
this.value = value;
}
public Number getValue() {
return value;
}
public void setValue(Number value) {
this.value = value;
}
}
限制和影响
-
运行时类型检查的限制:
- 泛型类型在运行时被擦除,因此不能直接创建泛型数组:
// 编译错误 Box<Integer>[] boxes = new Box<Integer>[10];
- 泛型类型在运行时被擦除,因此不能直接创建泛型数组:
-
类型擦除后不能区分重载方法:
- 以下两个方法在擦除后将具有相同的签名,导致编译错误:
public void method(List<String> list) { } public void method(List<Integer> list) { }
- 以下两个方法在擦除后将具有相同的签名,导致编译错误:
总结
泛型擦除是Java泛型类型系统的重要组成部分,它在编译时移除了泛型类型的信息,从而保持了与非泛型代码的兼容性。