Java General Method

Consider this code:

public <T> List<T> meth(List<?> type) { System.out.println(type); // 1 return new ArrayList<String>(); // 2 } 

It does not compile on line 2, saying a list is required.

Now, if it has changed to:

 public <T> List<?> meth(List<T> type) { System.out.println(type); // 1 return new ArrayList<String>(); // 2 } 

It compiles. What for? I thought the difference between a generic type declaration with T and using a wildcard was that when using a wildcard, you cannot add new elements to the collection. Why <?> Allow returning a subtype of List? Am I missing something, what is the explicit rule and how does it apply?

+2
source share
3 answers

The difference is in declaring the type of the return value. List<String> not a subtype of List<T> , but is a subtype of List<?> .

List<?> Makes no assumptions about its type variable, so the following statements are valid:

 List<?> l0 = new ArrayList<String>(); List<?> l1 = new ArrayList<Object>(); List<? extends Number> ltemp = null; List<?> l2 = ltemp; 

List<T> implies that the type argument will be resolved in the client context (for example, using the type) if you declared it as List<String> or List<Object> . Inside the body of the method, you also cannot make any assumptions about it.

+4
source

In the first case, T not necessarily a superclass of String . If you select T as Integer and call the method, it will fail; therefore it will not compile. However, the second one will compile just as confidently, any ArrayList<String> is a valid List of something.

+1
source

As mentioned earlier, String is not a subtype of T, so it does not work. However, this code works:

 public <T> List<T> meth(List<?> type) { System.out.println(type); // 1 return new ArrayList<T>(); // 2 } 

and I’m thinking more about what you want.

+1
source

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


All Articles