generics和问号

我想使用通用列表,但初始化方法只返回一个List 。 以下代码运行良好:

 List tmpColumnList = aMethodToInitializeTheColumnList(); tmpColumnList.add("ANICELITTLECOLUMN"); 

Java指责我使用的是原始类型,我应该对列表进行参数化。 所以我添加了问号参数化这个列表。

 List tmpColumnList = aMethodToInitializeTheColumnList(); tmpColumnList.add("ANICELITTLECOLUMN"); 

问题是:现在add(..)方法不再起作用了。
我不能保证列表只包含String因为我的代码中没有实现aMethodToInitializeTheColumnList()

我的错是什么?

谢谢!

来自generics教程。 感谢Michael的回答 !

然而,向它添加任意对象是不安全的:

 Collection c = new ArrayList(); c.add(new Object()); // Compile time error 

由于我们不知道c的元素类型代表什么,我们无法向其添加对象。 add()方法接受类型为E的参数,即集合的元素类型。 当实际类型参数是?时,它代表某种未知类型。 我们传递给add的任何参数都必须是这种未知类型的子类型。 因为我们不知道它是什么类型,所以我们无法传递任何内容。唯一的例外是null,它是每种类型的成员。

您可能希望使用List – 这就是Generics的用途,即添加有关集合中哪种对象的信息。 如果您实际上要使用包含混合类型的List(通常是设计不良的标志),请使用List

有关使用通配符的更多信息,请查看generics教程 。 但是在定义自己的generics类或具有generics参数的方法时,它们才真正相关。

如果使用 ,则表示您不会在任何地方使用参数化类型。 要么转到特定类型(在您的情况下似乎是List ),要么转到非常通用的List

在这种情况下,另一种选择是将您的列表声明为a

 List 

因为这个模型正是你所了解的。 你说你不确切知道它的类型边界是什么,但从你的第二行开始,假设它必须能够包含字符串是公平的。

这个编译并且在我看来,它比List更好一点,因为它编码了你在列表中实际可以进入的不确定性。 基本上,你只能向它添加字符串,但是当你调用get() ,返回的元素可以是任何东西(并且Java会正确地将这种类型推断为Object )。

实际上,这与List之间的唯一区别是后者允许tmpColumnList.add(3)tmpColumnList.add(new Thread())等。我更喜欢它所带来的语义以及实用性。

List表示列表是(或可以)键入,但类型未知**。 因此,添加一些内容可能是错误的**,如果您碰巧不属于该类型。 因为它是未知的,所以你会受到警告。

您可以使用List ,这意味着可以包含任何类型的列表