The one using the unbounded wildcard (?) actually means ? extends Object
(anything that extends Object).
This, in Java, implies a read-only nature, namely, we are allowed to read items from the generic structure, but we are not allowed to put anything back in it, because we cannot be certain of the actual type of the elements in it.
Therefore, I daresay it is a very valid approach in the printCollection
method under discussion, at least, until we meet a situation in which we need to assume a type.
If had to choose between them two, I would say that the second one (with type parameter T) is a cleaner approach because you can at least assume that the collection has a certain type T
, and that can prove to be useful in certain scenarios.
For example, if the Collection needed to be synchronized, I could simply do:
<T> void printCollection(Collection<T> c) {
List<T> copy = new ArrayList<T>();
synchronized(c) {
copy.addAll(c);
}
for (T e : copy) {
System.out.println(e);
}
}
I very easily created a new collection of type T
, and copy all elements of the original collection into this second one. This I can do, because I can assume the type of the collection is T
, and not ?
.
I could, of course, do the same thing with the first method (using the ubounded wildcard), but it's not so clean, I had to make assumptions that the type of the Collection is Object, and not ?
(which cannot be validly used as type argument: new ArrayList<?>()
).
void printCollection(Collection<?> c) {
List<Object> copy = new ArrayList<Object>();
synchronized(c) {
copy.addAll(c);
}
for (Object e : copy) {
System.out.println(e);
}
}
void printCollection(Collection<T> c)
or<T> void printCollection(Collection<T> c)
? The latter is a generic method. The former is not a generic method and must be declared in a generic class with a type parameterT
– Defeasible