Java泛型四:泛型实现原理之类型擦除

时间:2022-11-04 16:59:25

泛型类型实现原理相关的两个概念:原始类型、类型擦除。

原始类型

Java总是会自动的为泛型类型提供一个相应的原始类型。所谓原始类型就是是指泛型的第一个限定类型(从左向右),无限定类型泛型的原始类型默认为Object。

举例:

public class Rectangle<T> {}

等价于

public class Rectangle<T extends Object> {}

因此T的原始类型为Object。

public class Rectangle<T extends Number> {}

T的原始类型为Number。

public class Container<K extends Comparable& Serializable, V> {}

K的原始类型为Comparable,V的原始类型为Object

public class Container<K extends Serializable & Comparable, V> {}

调整extends Serializable & Comparable顺序后,K的原始类型为Serializable ,V的原始类型为Object

注意:extends后可以继承多个类、多个接口,原始类型为从左向右排序的第一个类或者接口。为了提高效率,应该将标签接口(即没有方法的接口)放在边界限定列表的末尾。清楚了原始类型之后,我们接下来讲解类型擦除。

类型擦除

Java中泛型的实现原理是类型擦除(type erasure)。类型擦除是在编译器进行代码编译这个阶段进行的,在编译的时候泛型的类型参数会被原始类型(raw type)所替代。
先来看个例子:
类1:

public class Container<K extends Integer, V extends String> {
private K key;
private V value;

public Container(K k, V v) {
key = k;
value = v;
}

public K getKey() {
return key;
}

public void setKey(K key) {
this.key = key;
}

public V getValue() {
return value;
}

public void setValue(V value) {
this.value = value;
}
}

类2:

public class Container {
private Integer key;
private String value;

public Container2(Integer k, String v) {
key = k;
value = v;
}

public Integer getKey() {
return key;
}

public void setKey(Integer key) {
this.key = key;
}

public String getValue() {
return value;
}

public void setValue(String value) {
this.value = value;
}
}

根据类型擦除的原理,泛型类1编译后的字节码与泛型类2编译后的字节码是一致的。