I am trying to understand java generics and they seem extremely difficult to understand. For example, this is fine...
public class Main {
public stati
The main thing to understand with generic types, is that they aren't covariant.
So whilst you can do this:
final String string = "string";
final Object object = string;
The following will not compile:
final List strings = ...
final List
This is to avoid the situations where you circumvent the generic types:
final List strings = ...
final List
So, going through your examples one by one
Your generic method takes a List, you pass in a List>; which is (essentially) a List. T can be assigned to the Object type and the compiler is happy.
Your generic method is the same, you pass in a List. >
T can be assigned to the List> type and the compiler is again happy.
This is basically the same as 2 with another level of nesting. T is still the List> type.
Here is where it goes a little pear shaped, and where my point from above comes in.
Your generic method takes a List. You pass in a >
List. Now, as generic types are not covariant, >
List> cannot be assigned to a List.
The actual compiler error (Java 8) is:
required:
java.util.Listfound:> java.util.Listreason: cannot infer type-variable(s)> T(argument mismatch;java.util.Listcannot be converted to> java.util.List)>
Basically the compiler is telling you that it cannot find a T to assign because of having to infer the type of the List nested in the outer list.
Lets look at this in a little more detail:
List> is a List of some unknown type - it could be a List or a List; we can get from it as Object, but we cannot add. Because otherwise we run into the covariance issue I mentioned.
List is a >
List of List of some unknown type - it could be a List or a >
List. In case 1 it was possible to assign >
T to Object and just not allow add operations on wildcard list. In case 4 this cannot be done - primarily because there is not a generics construct to prevent add to the outer List.
If the compiler were to assign T to Object in the second case then something like the following would be possible:
final List> list = ...
final List> wildcard = list;
wildcard.add(Arrays.asList("oops"));
So, due to covariance, it is not possible to assign a List to any other generic >
List safely.