Creating new generic object with wildcard

后端 未结 2 1172
耶瑟儿~
耶瑟儿~ 2020-11-27 21:33

Please explain this generic code wildcard compile time error:

//no compile time error.
List x = new ArrayList<>(); 

//compile          


        
相关标签:
2条回答
  • 2020-11-27 22:17

    It's invalid syntax to instantiate a generic type with wildcards. The type List<? extends Number> means a List of some type that is or extends Number. To create an instance of this type doesn't make sense, because with instantiation you're creating something specific:

    new ArrayList<? extends Number>();//compiler:"Wait, what am I creating exactly?" 
    

    Generic types with wildcards only make sense for variables and method parameters, because this allows greater freedom in what can be assigned/passed into them.

    //compiler:"Okay, so passing in a List<Integer> or a List<Double> are both fine"
    public void eatSomeNumbers(List<? extends Number> numbers) {
        for (Number number : numbers) {
            System.out.println("om nom " + number + " nom");
        }
    }
    

    Make sure to keep in mind the limitations that come with using wildcards.

    List<? extends Number> numList = ...
    numList.add(new Integer(3));//compiler:"Nope, cause that might be a List<Double>"
    

    As for your first example, the diamond is a new feature in Java 7 that allows the compiler to infer the type of the new generic instance, based on the type of the variable it's assigned to. In this case:

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

    The compiler is most likely inferring new ArrayList<Number>() here, but what's inferred hardly matters, as long as it's a valid assignment to the given variable. This was the reason for the diamond operator being introduced - that specifying the generic type of a new object was redundant, as long some generic type would make it a valid assignment/argument.

    This reasoning only makes sense if you remember that generics in Java are a purely compile-time language feature, because of type erasure, and have no meaning at runtime. Wildcards exist only because of this limitation. By contrast, in C# generic type information sticks around at runtime - and generic wildcards don't exist in that language.

    0 讨论(0)
  • 2020-11-27 22:29

    Use

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

    instead.

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