考虑这个例子来自一本书,有一个超类Gen和一个子类Gen2 ...
class Gen<T> { }
class Gen2<T> extends Gen<T> { }
Run Code Online (Sandbox Code Playgroud)
现在这本书的状态将不会编译(让我们假设它在一个主方法中)
Gen2<Integer> obj = new Gen2<Integer>();
if (obj instanceof Gen2<Integer>) {
//do something
}
Run Code Online (Sandbox Code Playgroud)
无法编译,因为运行时不存在泛型类型信息.如果它在运行时不存在,它何时存在?我认为它在编译时不会存在,但会在运行时存在.当然,以下适用于带有通配符的运行时...
if (obj instanceof Gen<?>) {
//do something else
}
Run Code Online (Sandbox Code Playgroud)
所以要澄清一下,我的问题是为什么通用类型信息在运行时不存在?我忽略了一个简单的概念吗?
问题是java中并不总是存在泛型(我认为它们在1.5中添加了它).因此,为了能够实现向后兼容性,存在类型擦除,其在编译代码时有效地擦除泛型类型信息以实现该目标.
摘自官方文件的相关部分:
在类型擦除过程中,Java编译器将擦除所有类型参数,并在类型参数有界时将其替换为第一个绑定,如果类型参数为无界,则替换为Object.
所以这段代码就是例子
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; }
// ...
}
Run Code Online (Sandbox Code Playgroud)
在类型擦除后成为这个:
public class Node {
private Comparable data;
private Node next;
public Node(Comparable data, Node next) {
this.data = data;
this.next = next;
}
public Comparable getData() { return data; }
// ...
}
Run Code Online (Sandbox Code Playgroud)
然而,如果你走的是像光剑一样的反射路径,有一种方法可以复活一些类型的信息:强大而又危险.