Fancy generics capture collision

后端 未结 5 1267
星月不相逢
星月不相逢 2021-01-05 07:19

Please give me a hint as to what is going on here:

List a = new ArrayList();
List b = new Array         


        
相关标签:
5条回答
  • 2021-01-05 07:50

    Don't use the ? wildcard. It means "Some specific type I don't know", and since you don't know the type, you can't add anything to the list. Change your code to use List<Number> and everything will work.

    This is fast becoming the most frequently asked Java question, in a hundred variations...

    0 讨论(0)
  • 2021-01-05 07:52

    You have essentially two lists of possibly different types. Because ? extends Number means a class which extends Number. So for list a it can be classA and for list b it can be for example classB. They are not compatible, they can be totally different.

    0 讨论(0)
  • 2021-01-05 08:02

    PECS (producer-extends, consumer-super)

    • You cannot put anything into a type declared with an EXTENDS wildcard except for the value null, which belongs to every reference type
    • You cannot get anything out from a type declared with an SUPER wildcard except for a value of type Object, which is a super type of every reference type
    0 讨论(0)
  • 2021-01-05 08:07

    The problem is that if you use List<? extends Number> you could actually do:

    List<? extends Number> a = new ArrayList<Integer>();
    List<? extends Number> b = new ArrayList<Double>();
    
    a.addAll(b); //ouch, would add Doubles to an Integer list
    

    The compiler can't tell from List<? extends Number> what the actual type parameter is and thus won't let you do the add operation.

    You also shouldn't cast the lists to List<Number> if you get them as a parameter, since you could actually have a list of Integer objects and add Double objects to it.

    In that case you better create a new List<Number> and add the objects from both lists:

    List<Number> c = new ArrayList<Number>(a.size() + b.size());
    c.addAll(a);
    c.addAll(b);
    

    Edit: in case you create both lists locally, you would not neet the ? wildcard anyway (since you'd always have List<Number>).

    0 讨论(0)
  • 2021-01-05 08:08

    The thing is:

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

    could also be read as:

    List<x extends Number> a = new ArrayList<Number>();
    List<y extends Number> b = new ArrayList<Number>();
    

    How should the compiler know that x and y are the same?

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