What is the purpose of using a wildcard for unbounded or upper-bounded generics? More specifically:
Why would I say public static void foo(List<?> bar)
instead of public static <E> void foo(List<E> bar)
?
Why would I say public static void foo(List<? extends Baz> bar)
instead of public static <E extends Baz> void foo(List<E> bar)
?
If you are not ever going to refer to E
in the code that follows, there is no need to declare it.
Reduces programmer memory strain.
The versions with a wildcard are preferred. If a parameter has type List<?>
it is clear that any List
will be accepted. If any List
is accepted, there's no reason to give the type parameter a name, so writing <E>
would just be clutter. On the other hand, if the type parameter appears twice in the signature, then you cannot use wildcards. For example, this signature needs a type parameter.
public static <E> List<E> combineLists(List<E> list1, List<E> list2)
Actually in that example it would probably be better if the arguments had type List<? extends E>
(the only way to do that without wildcards would be to have three type parameters, a total mess).
In Effective Java, it is recommended that even if the type parameter is needed in the body of the method, you should prefer the version of the signature with a wildcard, and write a private helper method to make this possible. For example:
public static void swapFirstAndLast(List<?> list) {
helper(list);
}
private static <E> void helper(List<E> list) {
int size = list.size();
E e = list.get(0);
list.set(0, list.get(size - 1)); // These lines would not be possible
list.set(size - 1, e); // If the type of list were List<?>
}
If the type of the list is decided at runtime, then you will need to use wildcards.
The following program will print a List<String>
if run with any command-line arguments; otherwise it will print a List<Number>
:
public class Test {
public static List<String> listOfStrings = Arrays.asList("hello", "world");
public static List<Number> listOfNumbers = Arrays.asList(1, 2, 3, 4.5);
public static List<?> getListOfUnknown(boolean arg) {
if(arg) return listOfStrings;
else return listOfNumbers;
}
public static void main(String[] args) {
System.out.println(getListOfUnknown(args.length > 0));
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With