类型擦除
泛型被引入到Java语言中,以便在编译时提供更严格的类型检查并支持泛型编程。为了实现泛型,Java编译器将类型擦除应用于:
- 如果类型参数是无界的,则用泛型或对象替换泛型类型中的所有类型参数。因此,生成的字节码仅包含普通的类、接口和方法。
- 如有必要,插入类型铸件以保持类型安全。
- 生成桥接方法以保留扩展泛型类型中的多态性。
类型擦除能够确保不为参数化类型创建新类,因此,泛型不会产生运行时开销。
擦除泛型类型
在类型擦除过程中,Java编译器将擦除所有类型参数,并在类型参数有界时将其替换为第一个绑定,如果类型参数为无界,则替换为Object。
考虑以下表示单链表中节点的泛型类:
public class Node<T> {
private T data;
private Node<T> next;
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
public T getData() { return data; }
// ...
}
因为类型参数T是无界的,所以Java编译器做完相应的类型检查之后,实际上到了运行期间上面这段代码实际上将转换成:
public class Node {
private Object data;
private Node next;
public Node(Object data, Node next) {
this.data = data;
this.next = next;
}
public Object getData() { return data; }
// ...
}
在以下示例中,泛型Node类使用有界类型参数:
public class Node<T extends Comparable<T>> {
private T data;
private Node<T> next;
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
public T getData() { return data; }
// ...
}
这意味着不管我们声明 Node 还是Node,到了运行期间,JVM 统统视为Node