问题
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 errorSince 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