问题
I've read a few topics which cover certain questions about generics, such as their relationship with raw types. But I'd like an additional explanation on a certain line found in the Java SE tutorial on unbound generics .
According to a sentence :
The goal of printList is to print a list of any type, but it fails to achieve that goal — it prints only a list of Object instances; it cannot print List<Integer>, List<String>, List<Double>, and so on, because they are not subtypes of List<Object>.
If I understand well this sentence; the difference between List<?>
and List<Object>
, is that we can use the type argument List<String>
or List<Integer>
by implementing the former. While if we implement the later, we can only use the type argument List<Object>
. As if List<?>
is an upper bound to Object
namely List<? Object>
.
But then the following sentence confuses me, in the sense that according to what I previously understood, List<Object>
should only contain instances of the class Object
and not something else.
It's important to note that
List<Object>
andList<?>
are not the same. You can insert an Object, or any subtype of Object, into aList<Object>
. But you can only insertnull
into aList<?>
.
回答1:
There are two separate issues here. A List<Object>
can in fact take any object as you say. A List<Number>
can take at least Number
objects, or of course any subclasses, like Integer
.
However a method like this:
public void print(List<Number> list);
will actually only take a List
which is exactly List<Number>
. It will not take any list which is declared List<Integer>
.
So the difference is List<?>
will take any List with whatever declaration, but List<Object>
will only take something that was declared as List<Object>
, nothing else.
The last quote simply states, that List<?>
is a list for which you literally don't know what type its items are. Because of that, you can not add anything to it other than null
.
回答2:
The sentence that is confusing you is trying to warn you that, while List<?>
is the super-type of all generic lists, you cannot add anything to a List<?>
collection.
Suppose you tried the following code:
private static void addObjectToList1(final List<?> aList, final Object o ) {
aList.add(o);
}
private static void addObjectToList2(final List<Object> aList, final Object o ) {
aList.add(o);
}
private static <T> void addObjectToList3(final List<T> aList, final T o ) {
aList.add(o);
}
public static void main(String[] args) {
List<String> testList = new ArrayList<String>();
String s = "Add me!";
addObjectToList1(testList, s);
addObjectToList2(testList, s);
addObjectToList3(testList, s);
}
addObjectToList1
doesn't compile, because you cannot add anything except null
to a List<?>
. (That's what the sentence is trying to tell you.)
addObjectToList2
compiles, but the call to it in main()
doesn't compile, because List<Object>
is not a super type of List<String>
.
addObjectToList3
both compiles and the call works. This is the way to add elements to a generic list.
来源:https://stackoverflow.com/questions/35272848/java-generics-unbound-wildcards-vs-object