? extends vs ? super
TL;DR
? extends T(Upper Bound): Use when you only need to read/get values from a generic structure.? super T(Lower Bound): Use when you only need to write/put values into a generic structure.
Concept
Choosing between extends and super wildcards is the most difficult part of Java Generics.
The extends wildcard (Covariance)
A List<? extends Number> means “a list of some unknown type, as long as that type is Number or a child of Number”.
- Reading: Safe. You know for a fact that whatever is inside is at least a
Number. - Writing: Unsafe. The list might actually be a
List<Double>. If you try to add anInteger, it will crash. Thus, writing is forbidden by the compiler.
The super wildcard (Contravariance)
A List<? super Integer> means “a list of some unknown type, as long as that type is Integer or a parent of Integer (like Number or Object)”.
- Reading: Unsafe. You don’t know what type you will get back (it could be an
Object). You can only retrieve data as a rawObject. - Writing: Safe. Whether the underlying list is a
List<Integer>,List<Number>, orList<Object>, anIntegeris a valid child of all of those.
Examples
import java.util.ArrayList;
import java.util.List;
public class ExtendsVsSuper {
// Use EXTENDS when you want to READ from the list
public static void processNumbers(List<? extends Number> list) {
for (Number num : list) { // Safe to read as Number
System.out.println(num.doubleValue());
}
// list.add(10); // COMPILE ERROR! Cannot write.
}
// Use SUPER when you want to WRITE to the list
public static void populateIntegers(List<? super Integer> list) {
list.add(10); // Safe to write Integer
list.add(20);
// Integer i = list.get(0); // COMPILE ERROR! Cannot safely read as Integer.
}
public static void main(String[] args) {
List<Double> doubles = new ArrayList<>(List.of(1.5, 2.5));
processNumbers(doubles); // Read-only access
List<Number> numbers = new ArrayList<>();
populateIntegers(numbers); // Write-only access
}
}
Interview Questions
Q: Can you use ? extends and ? super at the same time?
A: No. You cannot write <? extends Number super Integer>. Java wildcards allow you to define either an upper bound or a lower bound, but not both simultaneously.
Q: What happens if you try to read from a ? super T collection?
A: You can technically read from it, but the compiler will only guarantee that the elements are of type Object. If you have a List<? super Integer>, the compiler knows the list could actually be a List<Object>. Therefore, Object obj = list.get(0); is valid, but Integer i = list.get(0); will cause a compilation error.