Java generics - target of template except for lower bounds?

What is the purpose of using a wildcard for unlimited or limited generalizations? More specific:

Why should I say public static void foo(List<?> bar) instead of public static <E> void foo(List<E> bar) ?

Why should I say public static void foo(List<? extends Baz> bar) instead of public static <E extends Baz> void foo(List<E> bar) ?

+5
source share
3 answers

Wildcard versions are preferred. If the parameter is of type List<?> , Then it is clear that any List will be accepted. If any List accepted, there is no reason to specify a parameter of type name, so the <E> record will be just messy. On the other hand, if a type parameter appears twice in the signature, you cannot use wildcards. For example, a type parameter is required for this signature.

 public static <E> List<E> combineLists(List<E> list1, List<E> list2) 

Actually, in this example, it would be better if the arguments were of type List<? extends E> List<? extends E> (the only way to do this without wildcards is to have three type parameters, complete mess).

In Efficient Java, it is recommended that even if a type parameter is needed in the method body, you should prefer a wildcard version of the signature and write a private helper method to make this possible. For instance:

 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<?> } 
+2
source

If you are not going to reference E in the following code, there is no need to declare it.

Reduces the memory load of the programmer.

+4
source

If the type of the list is determined at runtime, you will need to use wildcards.

The following program will print a List<String> at startup 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)); } } 
+2
source

Source: https://habr.com/ru/post/1210626/


All Articles