无界通配符类型如何在运行时工作?

时间:2018-04-11 12:53:01

标签: java generics

我知道无界通配符类型将被删除并替换为Object vy类型擦除,无界通配符类型是可再生类型,类型信息在运行时完全可用。我知道List<Object> , List, List<?>之间的区别。我知道编译时List<?>是什么。我知道List<?>存储未知类型。 我知道它具有强大的编译时安全性和灵活性,但我想知道运行时会发生什么。

但我无法理解List&lt;?&gt;在运行时。

是对象引用列表吗? 它是原始类型List吗?

例如

List<?> list = new ArrayList<Integer>();

运行时的列表是什么以及如何表现?

我阅读了所有java语言规范,请不要只是把我的常见问题解答。

请注意,我阅读了以下问题,但我找不到答案(可以重复)

Generics Java, unbounded wildcard

2 个答案:

答案 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())

一旦编译器证明源代码是正确的,类型变量就会被抛弃(在一个称为擦除的过程中),在结果字节码中,变量的类型只是ListList<?> } List<Object>)。 运行时List<String>List<Integer>之间没有区别。 JVM无法说明。只有编译器知道,并且一旦编译完信息就永远消失了 (好吧,字节码实际上知道编译新Java源代码所需的最小值)

作为参考,请参阅ArrayList

的实施
public class ArrayList<E> implements List<E> {
    Object[] elementData; // ← array of Object
    int size;
}

LinkedList

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;
        }
    }
}