When should I use <T extends Number> vs ? extends Number in Java generics?

I'm trying to understand the difference between using a generic type parameter and a wildcard in Java generics.
Consider the following two simple examples:
Example 1:
public static <T extends Number> void print(List<T> list)
Example 2:
public static void print(List<? extends Number> list)
Both allow me to pass in a List, List, etc., and iterate over the elements. But I’m unclear about when would someone prefer to use a wildcard (Example 2 over 1)?
Could someone make this clear to me?
Answer
Maybe I think
When to Use Which?
Scenario | Use This | Reason |
---|---|---|
You only read from the list, not write | List<? extends Number> (Example 2) |
More flexible, avoids unnecessary type binding |
You need to write to the list or return elements | <T extends Number> List<T> (Example 1) |
Preserves type information, allows safe write operations |
example
first case:
public static void printList(List<? extends Number> list) {
for (Number num : list) {
System.out.println(num); // You can read elements
}
// list.add(123); // Compile error: cannot add, exact type is unknown
}
- usage
List<Integer> ints = List.of(1, 2, 3);
printList(ints); // OK
List<Double> doubles = List.of(1.1, 2.2);
printList(doubles); // OK
second case:
public static <T extends Number> void copyList(List<T> source, List<T> destination) {
for (T item : source) {
destination.add(item); // Safe to write
}
}
- usage:
List<Integer> src = new ArrayList<>(List.of(1, 2, 3));
List<Integer> dst = new ArrayList<>();
copyList(src, dst); // OK, T is Integer
Enjoyed this question?
Check out more content on our blog or follow us on social media.
Browse more questions