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

Java 无界通配符类型在运行时如何工作?,java,generics,Java,Generics,我知道无界通配符类型将被擦除并替换为对象类型擦除,并且无界通配符类型是可重新定义的类型,其类型信息在运行时完全可用。我知道List,List,List之间的区别。我知道编译时的列表是什么。我知道列表存储未知类型。 我知道它有很强的编译时安全性和灵活性,但我想知道在运行时会发生什么 但我无法理解在运行时列表是什么 它是对象引用的列表吗? 是原始类型列表吗 比如说 List<?> list = new ArrayList<Integer>(); List List=new

我知道无界通配符类型将被擦除并替换为对象类型擦除,并且无界通配符类型是可重新定义的类型,其类型信息在运行时完全可用。我知道
List,List,List
之间的区别。我知道编译时的
列表是什么。我知道
列表
存储未知类型。 我知道它有很强的编译时安全性和灵活性,但我想知道在运行时会发生什么

但我无法理解在运行时列表是什么

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

比如说

List<?> list = new ArrayList<Integer>();
List List=new ArrayList();
运行时的列表是什么以及如何操作

我阅读了所有java语言规范,请不要当着我的面抛出一个常见问题

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


好吧,在您的示例中,通配符不是无界的

List<?> list =new ArrayList<Integer>();
将不会编译,并向您抛出以下错误:

Cannot instantiate the type ArrayList<?>
无法实例化类型ArrayList

当涉及到接口时,通配符是可以接受的,但是您将无法使用通配符“直接”实例化任何对象。您必须在实现中的某个地方,告诉接口您希望他持有哪种类型的对象。即使它意味着
List

泛型主要发生在编译时。编译器使用
列表
声明中的信息来允许
列表.add(“Foo”)
和不允许使用编译时错误
列表.add(new Date())

一旦编译器证明源代码是正确的,类型变量就会被丢弃(在一个称为擦除的过程中),在生成的字节码中,变量的类型就是
List
(既不是
List
,也不是
List
运行时
列表
列表
之间没有区别。JVM无法判断。只有编译器知道,一旦编译完成,信息就永远消失了(好吧,字节码实际上知道编译新Java源代码所需的最低限度)

作为参考,请参见以下内容的实施:


泛型主要发生在编译时,而泛型只发生在编译时:)一个需要实用,但也要100%正确。关于整个泛型机制的一小部分信息在编译器中保存下来,并写入字节码,以便其他工具(有时JVM本身带有反射)可以阅读。谢谢。我已经知道编译时类型安全。列表在运行时存储了什么?我想通过使用反射列表检索一个对象来查找列表中存储的内容。get(0)。getClass();但是编译器安全不允许编译这段代码。我不知道你在说什么代码,但是你不能通过在运行时玩反射来猜测类型变量的类型。想象一下,一个
列表包含一个字符串和一个IntegerThanks。我如何知道类型变量的类型?谢谢。谢谢。如果列表包含整数,为什么我不能在列表后面添加整数?列表是否存储引用整数的对象引用?我是否正确?因为编译器本身(请注意,您不在运行时)不允许您这样做,原因很多,超出了我的知识范围。我会问这个问题,这是一个有趣的事实。顺便说一下,@3code,以下是您关于为什么不能添加整数的答案:
Cannot instantiate the type 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;
        }
    }
}