Generics, Type Parameters and Wildcards

前端 未结 1 1546
挽巷
挽巷 2020-12-03 01:21

I am trying to understand java generics and they seem extremely difficult to understand. For example, this is fine...

public class Main {

    public stati         


        
1条回答
  •  醉梦人生
    2020-12-03 01:58

    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 objects = strings;
    
    
    

    This is to avoid the situations where you circumvent the generic types:

    final List strings = ...
    final List objects = strings;
    objects.add(1);
    final String string = strings.get(0); <-- oops
    
    
    

    So, going through your examples one by one

    1

    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.

    2

    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.

    3

    This is basically the same as 2 with another level of nesting. T is still the List type.

    4

    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.List> found: java.util.List> reason: cannot infer type-variable(s) T (argument mismatch; java.util.List> cannot 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.

    0 讨论(0)
    提交回复
    热议问题