Generics and the question mark

扶醉桌前 提交于 2020-01-20 03:07:27

问题


I'd like to use a generic list, but the initialization method only returns a List. The following code works well:

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.

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

Problem is: Now the add(..) method doesn't work anymore.
I cannot assure that the list only contains Strings as aMethodToInitializeTheColumnList() is not implemented in my code.

What is my mistake?

Thanks!


回答1:


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.




回答2:


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>

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.




回答3:


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>




回答4:


Another option in this case would be to declare your list to be a

List<? super String>

since this models exactly what 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 add Strings to it, but when you call get() the returned element could be anything (and Java will correctly infer this type to be 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.




回答5:


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.

You can use List<Object>, which means a list that can contain any type.



来源:https://stackoverflow.com/questions/1839969/generics-and-the-question-mark

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!