What's the difference between unbounded wildcard type List<?> and raw type List?
Could you help me understand the difference between unbounded wildcard type List and raw type List?
List<?> b; // unbounded wildcard type
List a; // raw type
Along with this can anybody help me understand what is a bounded type parameter list?
List<E extends Number> c;
Solution 1:
Here's a summary of the three:
List
: A list with no type parameter. It is a list whose elements are of any type -- the elements may be of different types.List<?>
: A list with an unbounded type parameter. Its elements are of a specific, but unknown, type; the elements must all be the same type.List<T extends E>
: A list with a type parameter calledT
. The supplied type forT
must be of a type that extendsE
, or it is not a valid type for the parameter.
Solution 2:
You should really look at Effective Java, Item 23: Don't use raw types in new code.
To use the example from that book, consider the following example... what if you have a collection where you do not care what types of elements are in it. For example, you want to see how many elements are in common between two sets. You might come up with the following:
public static int numElementsInCommon(Set s1, Set s2) {
int result = 0;
for (Object o : s1) {
if (s2.contains(o)) {
++result;
}
}
return result;
}
This example, while it works, is not a good idea to use because of the use of raw types. Raw types just aren't type safe at all... you could end up modifying the set in a way that is not type safe and corrupt your program. Instead, err on the side of caution and use the type safe alternative:
public static int numElementsInCommon(Set<?> s1, Set<?> s2) {
int result = 0;
for (Object o : s1) {
if (s2.contains(o)) {
++result;
}
}
return result;
}
The difference is that you can only add null
to a Set<?>
, and you CANNOT assume anything about the element you take out of a Set<?>
. If you use a raw Set
, you can add anything you want to it. The numElementsInCommon
method is a good example where you don't even need to add anything and you don't need to assume anything about what is in the set. That's why it's a good candidate for using the ?
wildcard.
Hope this helps. Read that whole Item in Effective Java and it will really become clear.
To answer the second part of your question... remember that I said when you use the ?
wildcard, you cannot assume anything about the element you take out of the set? What if you do need to make an assumption about the interface of the object you removed from the set. For example, suppose you want to keep track of a set of Cool
things.
public interface Cool {
// Reports why the object is cool
void cool();
}
Then you might have some code like this:
public static void reportCoolness(Set s) {
for (Object item : s) {
Cool coolItem = (Cool) item;
coolItem.cool();
}
}
This is not type safe... you need to make sure you passed in a set with only Cool
objects. To fix it, you might say:
public static void reportCoolness(Set<Cool> s) {
for (Cool coolItem : s) {
coolItem.cool();
}
}
This is great! Does exactly what you want and is type safe. But what if later you have this:
public interface ReallyCool extends Cool {
// Reports why the object is beyond cool
void reallyCool();
}
Since all ReallyCool
objects are Cool
, you ought to be able to do the following:
Set<ReallyCool> s = new HashSet<ReallyCool>();
// populate s
reportCoolness(s);
But you can't do that because generics have the following property: Suppose B
is a subclass of A
, then Set<B>
is NOT a subclass of Set<A>
. The technical talk for this is "Generic types are invariant." (As opposed to covariant).
To get the last example to work you would need to create a Set<Cool>
by casting (safely) every element in the Set<ReallyCool>
. To avoid letting clients of your api go through this nasty, unnecessary code, you can just make the reportCoolness
method more flexible like this:
public static void reportCoolness(Set<? extends Cool> s) {
for (Cool coolItem : s) {
coolItem.cool();
}
}
Now your method takes any Set
that contains elements that are Cool
or any subclass of Cool
. All of these types adhere to the Cool
api... so we can safely call the cool()
method on any element
Make sense? Hope this helps.