Java) Wildcards
This post was migrated from Tistory. You can find the original here.
Wildcards
Unlike arrays, generics don’t support covariance/contravariance.
1
2
3
4
5
6
7
8
9
// covariance
Object[] Covariance = new Integer[10];
// contravariance
Integer[] Contravariance = (Integer[]) Covariance;
// covariance
ArrayList<Object> Covariance = new ArrayList<Integer>();
// contravariance
ArrayList<Integer> Contravariance = new ArrayList<Object>();
Wildcards were introduced to work around this limitation.
1
2
3
4
5
6
7
8
9
10
11
12
13
class MyArrayList<T> {
Object[] element = new Object[5];
int index = 0;
// Constructor that takes a collection from the caller and adds all of its elements into the internal array to instantiate the object
public MyArrayList(Collection<? extends T> in) {
for(T elem : in) {
element[index++] = elem;
}
}
// ...
}
Wildcards should be thought of as something you use when consuming an already-defined generic class or method.
1
2
3
class Sample<? extends T> { // ! Error
}
In other words, this is not how you’re supposed to use them.
Getting values in and out with wildcard bounds
List<? extends U> bounds the upper type.
You can only read out U, and you can’t store anything into it.
List<? super U> bounds the lower type.
You can only read out Object, but you can store U or any of its subtypes.
List<?> has no bound at all.
You can only read out Object, and you can’t store anything (only null can be stored).
You can only read values out up to the upper bound, and you can only store values in down to the lower bound.
+α
Watch out for runtime errors caused by downcasting.