Java nested generic type mismatch

前端 未结 5 503
耶瑟儿~
耶瑟儿~ 2020-12-05 11:13

In the following example:

public static void main(String[] args) {

    List b = new ArrayList();
    first(b);
    second(b);

          


        
相关标签:
5条回答
  • 2020-12-05 11:33

    List<List<String>> is not same as List<List<?>>. Generics are invariant in nature. If you only do List<?> and pass List<String> then it will work because List of Anything can be represented by Lists of String.

    But List of List of anything can not be represented by List of List of String.

    @Lukas Elder has already specified case that will work. Here is the second case that will work

    private static void fourth(List<?> a){
        System.out.println("List of anything ");
    }
    
    0 讨论(0)
  • 2020-12-05 11:34

    A List<List<String>> isn't a List<List<?>>.

    You should be able to put any List<?> into a List<List<?>>, no matter what the ?. A List<List<String>> will only accept a List<String>.

    0 讨论(0)
  • 2020-12-05 11:43
    List<List<?>> == List {                 //That contains any unknown type lists
                            List<Integer>,
                            List<String>,
                            List<Object>
                          }
    

    Where as

    List<? extends List<?> == List {       //That contains same unknown type lists
                            List<Integer>,
                            List<Integer>,
                            List<Integer>
                          }
    

    So here

     List<List<String>> == List {        //That contains same String lists
                            List<String>,
                            List<String>,
                            List<String>
                          }
    

    Hence List<? extends List<?> is super type of List<List<String>> and assignable.

    So valid value to call your fourth method is below.

        List<List<?>> a1 =  new ArrayList<List<?>>();
        a1.add(new ArrayList<String>());
        a1.add(new ArrayList<Integer>());
        a1.add(new ArrayList<Object>());
    
    0 讨论(0)
  • 2020-12-05 11:45

    If you want to be able to call fourth with a List<List<String>> argument, then you'll need to change your signature to this:

    private static void fourth(List<? extends List<?>> a){
        System.out.println("List of a List of anything ");
    }
    

    The above will work because unlike List<List<?>>, List<? extends List<?>> is compatible with List<List<String>>. Think of it this way:

    List<List<String>> original = null;
    List<? extends List<?>> ok  = original; // This works
    List<?> ok2                 = original; // So does this
    List<List<?>> notOk         = original; // This doesn't
    
    List<Integer> original      = null;
    List<? extends Number> ok   = original; // This works
    List<?> ok2                 = original; // So does this
    List<Number> notOk          = original; // This doesn't
    

    The reasoning is simple. If you had

    private static void fourth(List<List<?>> a) {
        List<?> ohOh = Arrays.asList(new Object());
        a.add(ohOh);
    }
    

    And then if you could call that method as such:

    List<List<String>> a = new ArrayList<List<String>>();
    fourth(a);
    String fail = a.get(0).get(0); // ClassCastException here!
    
    0 讨论(0)
  • 2020-12-05 11:58

    This implies that the type is unknown and objects of any type can be added to List<List<?>> that are heterogeneous and compiler cannot guarantee that all object in List<List<?>> are of same type. Hence it cannot be passed to new ArrayList<List<String>>() that takes a bounded type as parameter.

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