Java Generic List>

后端 未结 5 1801
别那么骄傲
别那么骄傲 2020-11-30 02:06

How come in java we cannot do:

List> aList = new ArrayList>();

Even though thi

相关标签:
5条回答
  • 2020-11-30 02:50

    I'm not very familiar with Java syntax but it seems that your issue is this:

    Covariance & Contravariance

    0 讨论(0)
  • 2020-11-30 02:54

    You should definitely use the ? type wildcard when appropriate, do not avoid it as a general rule. For example:

    public void doThingWithList(List<List<? extends Number>> list);
    

    allows you to pass a List<Integer> or a List<Long>.

    public void doThingWithList(List<List<Number>> list);
    

    allows you to only pass arguments declared as List<Number>. A small distinction, yes, but using the wildcard is powerful and safe. Contrary to how it may seem, a List<Integer> is not a subclass, or is not assignable, from List<Number>. Nor is List<Integer> a subclass of List<? extends Number, which is why the code above does not compile.

    0 讨论(0)
  • 2020-11-30 02:55

    Your statement does not compile because List<? extends Number> is not the same type as List<Number>. The former is a supertype of the latter.

    Have you tried this? Here I'm expressing that the List is covariant in its type argument, so it will accept any subtype of List<? extends Number> (which includes List<Number>).

    List<? extends List<? extends Number>> aList = new ArrayList<List<Number>>();
    

    Or even this. Here the type parameter for the ArrayList on the right-hand side is the same as the type parameter on the left-hand side, so variance is not an issue.

    List<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();
    

    You should be able to just say

    List<List<Number>> aList = new ArrayList<List<Number>>();
    

    I tend to avoid the ? type wildcard whenever possible. I find that the expense incurred in type annotation is not worth the benefit.

    0 讨论(0)
  • 2020-11-30 02:56

    In Java, if Car is a derived class of Vehicle, then we can treat all Cars as Vehicles; a Car is a Vehicle. However, a List of Cars is not also a List of Vehicles. We say that List<Car> is not covariant with List<Vehicle>.

    Java requires you to explicitly tell it when you would like to use covariance and contravariance with wildcards, represented by the ? token. Take a look at where your problem happens:

    List<List<? extends Number>> l = new ArrayList<List<Number>>();
    //        ----------------                          ------
    // 
    // "? extends Number" matched by "Number". Success!
    

    The inner List<? extends Number> works because Number does indeed extend Number, so it matches "? extends Number". So far, so good. What's next?

    List<List<? extends Number>> l = new ArrayList<List<Number>>();
    //   ----------------------                    ------------
    // 
    // "List<? extends Number>" not matched by "List<Number>". These are
    //   different types and covariance is not specified with a wildcard.
    //   Failure.
    

    However, the combined inner type parameter List<? extends Number> is not matched by List<Number>; the types must be exactly identical. Another wildcard will tell Java that this combined type should also be covariant:

    List<? extends List<? extends Number>> l = new ArrayList<List<Number>>();
    
    0 讨论(0)
  • 2020-11-30 03:10
    List<List<? extends Number>> aList = new ArrayList<List<? extends Number>>();
    aList.add(new ArrayList<Integer>());
    
    0 讨论(0)
提交回复
热议问题