为什么&#34;新的ArrayList <e>&#34;是允许的吗?</e>

时间:2014-04-09 03:44:01

标签: java arraylist

我正在学习&#34; Java in a Nutshell&#34;第5版。在p169,它说&#34;记住, 但是,类型变量仅在编译时存在,因此您不能使用类型变量 与运行时运算符instanceof和new。&#34;。如果我理解正确(我是??),new和instanceof不应该与类型变量一起使用。但在我做了一些测试后,我变得更加困惑。

  1. 列表与LT; ?&GT; l = new ArrayList&lt; ?&GT;(); //未编译,我可能知道原因
  2. 列表与LT; e基l = new ArrayList&lt; E - 代替;(); //编译!! WHY ??
  3. 有谁可以告诉我为什么(2)被允许?

    非常感谢任何信息。

3 个答案:

答案 0 :(得分:7)

声明“您不能将类型变量与new一起使用”意味着您无法执行此操作:

E e = new E(); // can't do this

但是你可以将类型变量传递给另一个类供它使用:

class MyClass<E> {
    List<E> = new ArrayList<E>(); // OK
}

您不是实例化 E,而是使用类型 ArrayList实例化E

关于使用?,这是一个不同的问题。 ?表示“未知”类型,而变量可以是未知类型,您不能通过指定未知类型实例化泛型类 - 您必须将已知的类型传递给泛型类。

但你可以编码:

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

答案 1 :(得分:2)

除非您已定义,E不是一个类。

E只是在编译期间引用类的一种方法。这样,可以用它调用适当的方法。

List<String> list1 = new ArrayList<String>(); // Diamond types for Java 7+
List<Integer> list2 = new ArrayList<Integer>();

// Populate lists

list1.get(0).charAt(0); // Perfectly fine, String#charAt(int) exists
list2.get(0).charAt(0); // Error! Integer doesn't have a charAt(int) method!

因此,E类中的类型ArrayList用于确保您可以在知道类型的情况下对元素执行操作,就好像它是该类型一样。这样可以避免在调用仅存在于特定类中的方法时遇到问题,正如我使用charAt(int)方法所示。

除此之外,还可以指出为什么你不能使用?拨打电话。

List<?> list1 = new ArrayList<String>(); // Fine
List<?> list2 = new ArrayList<?>();      // What type is this list composed of?

制作未知类型的列表没有意义。如果您想要一个泛型类型的列表,您始终可以将Object传递给泛型,但没有理由添加对创建具有未知类型的实例的支持。

答案 2 :(得分:0)

波西米亚人回答了一些“什么”,但我想对一些“为什么”采取行动。

让我们从无法做的事情开始吧。这一切都归结为erasure,这基本上意味着当您的代码有List<String>时,字节码信息只有List。字节码中缺少尖括号之间的任何内容(因此也没有来自运行时)。

那么,为什么你不能foo instanceof E?好吧,因为那是运行时检查,并且E在运行时是未知的。

为什么你不能new E()?同样,因为这需要运行时知道E是什么(它如何调用正确的构造函数?或者甚至确保存在无参数构造函数?),但该信息不可用。< / p>

在所有这些情况下,要记住的是,语言不会阻止您仅仅为了阻止您而做某事。它阻止你这样做,因为它不可能在运行时执行。

那么,为什么 你可以输入new ArrayList<String>()?因为运行时需要的唯一信息是ArrayList被实例化,并且它具有该信息。它是ArrayList String的事实对运行时无关紧要,因为擦除意味着ArrayList在运行时不知道或不关心它是什么的列表