我知道无界通配符类型将被删除并替换为Object vy类型擦除,无界通配符类型是可再生类型,类型信息在运行时完全可用。我知道List<Object> , List, List<?>
之间的区别。我知道编译时List<?>
是什么。我知道List<?>
存储未知类型。
我知道它具有强大的编译时安全性和灵活性,但我想知道运行时会发生什么。
但我无法理解List&lt;?&gt;在运行时。
是对象引用列表吗? 它是原始类型List吗?
例如
List<?> list = new ArrayList<Integer>();
运行时的列表是什么以及如何表现?
我阅读了所有java语言规范,请不要只是把我的常见问题解答。
请注意,我阅读了以下问题,但我找不到答案(可以重复)
答案 0 :(得分:3)
嗯,在您的示例中,您的通配符不无限制。
List<?> list =new ArrayList<Integer>();
运行时的列表是什么以及如何表现?
在运行时,您的列表是ArrayList
的实例,其中包含Integer
个对象。您链接的问题对于拥有通配符时会发生什么情况有很好的答案。请注意以下内容:
List<?> list = new ArrayList<?>();
无法编译,抛出以下错误:
Cannot instantiate the type ArrayList<?>
当涉及到接口时,接受通配符,但是您将无法使用通配符“直接”实例化任何对象。你必须以某种方式,在实现的某个地方,告诉你的界面你希望他拥有什么类型的对象。即使这意味着List<Object>
。
答案 1 :(得分:0)
泛型主要发生在编译时。编译器使用List<String>
声明中的信息来允许list.add("Foo")
并禁止编译时错误list.add(new Date())
。
一旦编译器证明源代码是正确的,类型变量就会被抛弃(在一个称为擦除的过程中),在结果字节码中,变量的类型只是List
(List<?>
} List<Object>
)。 运行时List<String>
和List<Integer>
之间没有区别。 JVM无法说明。只有编译器知道,并且一旦编译完信息就永远消失了 (好吧,字节码实际上知道编译新Java源代码所需的最小值)。
作为参考,请参阅ArrayList
:
public class ArrayList<E> implements List<E> {
Object[] elementData; // ← array of Object
int size;
}
public class LinkedList<E> {
int size = 0;
Node<E> first; // ← replaced with Node in bytecode
private static class Node<E> {
E item; // ← has type Object in bytecode
Node<E> next; // ← type Node in bytecode
Node<E> prev; // ← type Node in bytecode
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
}