Java 泛型和问号
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1839969/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Generics and the question mark
提问by guerda
I'd like to use a generic list, but the initialization method only returns a List
.
The following code works well:
我想使用通用列表,但初始化方法只返回一个List
. 以下代码运行良好:
List tmpColumnList = aMethodToInitializeTheColumnList();
tmpColumnList.add("ANICELITTLECOLUMN");
Java accuses that I'm using a raw type and I should paramerize the list. So I added the question mark parameterize this list.
Java 指责我使用的是原始类型,我应该参数化列表。所以我添加了问号参数化这个列表。
List<?> tmpColumnList = aMethodToInitializeTheColumnList();
tmpColumnList.add("ANICELITTLECOLUMN");
Problem is: Now the add(..)
method doesn't work anymore.
I cannot assure that the list only contains String
s as aMethodToInitializeTheColumnList()
is not implemented in mycode.
问题是:现在该add(..)
方法不再有效。
我不能保证列表只包含String
s,因为我的代码中aMethodToInitializeTheColumnList()
没有实现。
What is my mistake?
我的错误是什么?
Thanks!
谢谢!
采纳答案by guerda
From the Generics Tutorial. Thanks to Michael's answer!
来自泛型教程。感谢迈克尔的回答!
It isn't safe to add arbitrary objects to it however:
Collection<?> c = new ArrayList<String>(); c.add(new Object()); // Compile time error
Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type.Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type.
但是,向其中添加任意对象是不安全的:
Collection<?> c = new ArrayList<String>(); c.add(new Object()); // Compile time error
因为我们不知道 c 的元素类型代表什么,所以我们不能向它添加对象。add() 方法接受类型为 E 的参数,即集合的元素类型。当实际类型参数为 ? 时,它代表某种未知类型。我们传递给 add 的任何参数都必须是这种未知类型的子类型。因为我们不知道那是什么类型,所以我们不能传入任何东西。唯一的例外是 null,它是所有类型的成员。
回答by Michael Borgwardt
You probably want to use List<String>
- that's how Generics are intended to be used, i.e. add information about what kind of objects will be in a collection. If you're actually going to have a List containing mixed types (which is usually a sign of bad design) use List<Object>
您可能想要使用List<String>
- 这就是泛型的使用方式,即添加有关集合中将包含何种对象的信息。如果您实际上要包含一个包含混合类型的 List(这通常是糟糕设计的标志),请使用List<Object>
For more information about the use of wildcards, look at the Generics Tutorial. But they're really only relevant when defining your own generic classes, or methods with generic parameters.
有关使用通配符的更多信息,请查看泛型教程。但它们实际上仅在定义您自己的泛型类或具有泛型参数的方法时才相关。
回答by Romain
If you use <?>
, you mean you aren't going to use the parametrized type anywhere. Either go to the specific type (in your case it seems List<String>
) or to the very generic List<Object>
如果您使用<?>
,则意味着您不会在任何地方使用参数化类型。要么转到特定类型(在您的情况下似乎是List<String>
),要么转到非常通用的List<Object>
回答by KLE
The List<?>
means that the list is (or could be) typed, but the type is unknown**. So adding something to it could be wrong**, if you happen to be outside of the type. Because it is unknown, you are warned.
这List<?>
意味着列表已(或可能)已键入,但类型未知**。所以添加一些东西可能是错误的**,如果你碰巧在类型之外。因为它是未知的,所以你被警告。
You can use List<Object>
, which means a list that can contain any type.
您可以使用List<Object>
,这意味着可以包含任何类型的列表。
回答by Andrzej Doyle
Another option in this case would be to declare your list to be a
在这种情况下的另一种选择是将您的列表声明为
List<? super String>
since this models exactlywhat you know about it. You say that you don't know exactly what its type bounds are, but from your second line it's fair to assume that it must be able to contain strings.
因为这正是您所了解的模型。你说你不知道它的类型界限是什么,但是从你的第二行可以公平地假设它必须能够包含字符串。
This compiles and to my mind, is a little nicer than a List<Object>
as it encodes your uncertainty as to what can actually go in the list. Basically, you can only addStrings to it, but when you call get()
the returned element could be anything (and Java will correctly infer this type to be Object
).
在我看来,这个编译器比 a 好一点,List<Object>
因为它编码了您对列表中实际可以包含的内容的不确定性。基本上,您只能向其中添加字符串,但是当您调用get()
返回的元素时,它可以是任何内容(Java 会正确推断此类型为Object
)。
In practical terms, the only difference between this and List<Object>
is that the latter would allow tmpColumnList.add(3)
or tmpColumnList.add(new Thread())
etc. I much prefer the semantics it carries as well as the practicality.
实际上,这和List<Object>
它之间的唯一区别是后者允许tmpColumnList.add(3)
或tmpColumnList.add(new Thread())
等等。我更喜欢它所承载的语义以及实用性。