Careeroza
Wildcards
Generics Are Not Covariant
Integer is a Number, but List<Integer> is not a List<Number>. Wildcards (?) make methods flexible.
| Wildcard | Meaning | Can read as | Can add |
|---|---|---|---|
List<?> | list of unknown type | Object | nothing (except null) |
List<? extends Number> | Number or subtype (producer) | Number | nothing |
List<? super Integer> | Integer or supertype (consumer) | Object | Integer |
Tip: Remember PECS: Producer Extends, Consumer Super. If you read from it, use extends; if you write into it, use super.
Wildcards in Action
Example
import java.util.ArrayList;
import java.util.List;
public class Main {
static double total(List<? extends Number> prices) { // producer: read only
double sum = 0;
for (Number n : prices) sum += n.doubleValue();
return sum;
}
static void addDefaults(List<? super Integer> target) { // consumer: write Integers
target.add(10);
target.add(20);
}
static void printAll(List<?> items) {
System.out.println(items.size() + " items: " + items);
}
public static void main(String[] args) {
List<Integer> ints = new ArrayList<>(List.of(1, 2));
List<Double> doubles = List.of(1.5, 2.5);
System.out.println(total(ints) + " " + total(doubles));
List<Number> numbers = new ArrayList<>();
List<Object> objects = new ArrayList<>();
addDefaults(ints);
addDefaults(numbers);
addDefaults(objects);
printAll(ints);
printAll(numbers);
printAll(List.of("x", 'y', 3));
}
}Output
3.0 4.0 4 items: [1, 2, 10, 20] 2 items: [10, 20] 3 items: [x, y, 3]
Type Erasure
Generics exist only at compile time. The compiler checks types, then erases them: at runtime a List<String> and a List<Integer> are the same ArrayList class. That is why you cannot write new T(), T[] creation, or obj instanceof List<String>.
Example
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<String> a = new ArrayList<>();
List<Integer> b = new ArrayList<>();
System.out.println(a.getClass() == b.getClass());
System.out.println(a.getClass().getName());
}
}Output
true java.util.ArrayList