These are functionally identical. So the second one should be preferred as shorter :
public static void test(List<? extends Number> list) {
for (Number t : list) {
}
}
The first one makes more sense when you want to return something relying on the declared type.
For example this code is more flexible concerning the return type:
public static <T extends Number> List<T> test(List<T> list) {
for (T t : list) {
}
return list;
}
you can invoke it in this way :
List<Integer> integers = ...;
integers = test(integers);
because with a declared parameterized type used in the return type, the compiler infers the return type from the type of the variable which you assign the result of the method (that has to be compatible of course with the type constraint).
But as List<Integer>
is a subtype of List<? extends Number>
you can also use this way :
List<Integer> integers = ...;
List<? extends Number> numbers = test(integers);
Without declaring a parameterized type in the return type of the List, you can only assign the result of the method to a type declared with List<? extends Number>
:
public static List<? extends Number> test(List<? extends Number> list) {
for (Number t : list) {
}
return list;
}
So, only this way is valid :
List<Integer> integers = ...;
List<? extends Number> numbers = test(integers);