泛型和问号

时间:2009-12-03 13:50:50

标签: java generics

我想使用通用列表,但初始化方法只返回List。 以下代码效果很好:

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

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

List<?> tmpColumnList = aMethodToInitializeTheColumnList();
tmpColumnList.add("ANICELITTLECOLUMN");

问题是:现在add(..)方法不再起作用了 我无法保证该列表仅包含String,因为aMethodToInitializeTheColumnList()未在我的代码中实现。

我的错误是什么?

谢谢!

5 个答案:

答案 0 :(得分:27)

来自泛型教程。感谢Michael's answer

  

添加任意对象是不安全的   但是:

Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
     

因为我们不知道该是什么元素   c的类型代表,我们无法添加   对象。 add()方法需要   类型E的参数,即元素类型   的集合。当实际   类型参数是?,它代表   一些未知的类型。 我们的任何参数   传递给add必须是一个子类型   这种未知类型。因为我们没有   知道什么类型,我们不能通过   任何事情。唯一的例外是   null,是每种类型的成员。

答案 1 :(得分:17)

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

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

答案 2 :(得分:16)

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

答案 3 :(得分:8)

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

List<? super String>

因为这个模型完全你对它的了解。你说你不确切知道它的类型边界是什么,但是从你的第二行可以假设它必须能够包含字符串。

这在我的脑海中编译,比List<Object>好一点,因为它编码了你对列表中实际内容的不确定性。基本上,你只能添加字符串,但是当你调用get()时,返回的元素可以是任何东西(Java会正确推断这个类型为Object)。 / p>

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

答案 4 :(得分:2)

List<?>表示列表是(或可能),但类型未知**。所以添加一些东西可能是错误的**,如果你碰巧不属于这种类型。因为它是未知的,所以你会受到警告。

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

相关问题