我想使用通用列表,但初始化方法只返回List
。
以下代码效果很好:
List tmpColumnList = aMethodToInitializeTheColumnList();
tmpColumnList.add("ANICELITTLECOLUMN");
Java指责我使用的是原始类型,我应该对列表进行参数化。 所以我添加了问号参数化这个列表。
List<?> tmpColumnList = aMethodToInitializeTheColumnList();
tmpColumnList.add("ANICELITTLECOLUMN");
问题是:现在add(..)
方法不再起作用了
我无法保证该列表仅包含String
,因为aMethodToInitializeTheColumnList()
未在我的代码中实现。
我的错误是什么?
谢谢!
答案 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>
,这意味着可以包含任何类型的列表。