使用通配符创建新的通用对象 [英] Creating new generic object with wildcard
问题描述
请解释这个通用代码通配符编译时错误:
Please explain this generic code wildcard compile time error:
//no compile time error.
List<? extends Number> x = new ArrayList<>();
//compile time error.
List<? extends Number> x = new ArrayList<? extends Number>();
推荐答案
使用通配符实例化泛型类型是无效的语法.类型 List
表示 某种类型的 List
是或扩展 Number
.创建这种类型的实例没有意义,因为通过实例化您正在创建特定的东西:
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>"
对于您的第一个示例,菱形是 Java 7 中的一项新功能,它允许编译器根据分配给它的变量的类型推断新泛型实例的类型.在这种情况下:
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<>();
编译器很可能在此处推断 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.
这种推理只有在您记得 Java 中的泛型是纯粹的编译时语言特性时才有意义,因为 类型擦除,在运行时没有意义.通配符的存在只是因为这个限制.相比之下,在 C# 中,泛型类型信息在运行时仍然存在——并且该语言中不存在泛型通配符.
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.
这篇关于使用通配符创建新的通用对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!