泛型类型实现原理相关的两个概念:原始类型、类型擦除。
原始类型
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编译后的字节码是一致的。