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 super String>
因为这个模型正是你所了解的。 你说你不确切知道它的类型边界是什么,但从你的第二行开始,假设它必须能够包含字符串是公平的。
这个编译并且在我看来,它比List
更好一点,因为它编码了你在列表中实际可以进入的不确定性。 基本上,你只能向它添加字符串,但是当你调用get()
,返回的元素可以是任何东西(并且Java会正确地将这种类型推断为Object
)。
实际上,这与List
之间的唯一区别是后者允许tmpColumnList.add(3)
或tmpColumnList.add(new Thread())
等。我更喜欢它所带来的语义以及实用性。
List>
表示列表是(或可以)键入,但类型未知**。 因此,添加一些内容可能是错误的**,如果您碰巧不属于该类型。 因为它是未知的,所以你会受到警告。
您可以使用List
,这意味着可以包含任何类型的列表 。