使用通配符创建新的通用对象 [英] Creating new generic object with wildcard

查看:26
本文介绍了使用通配符创建新的通用对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请解释这个通用代码通配符编译时错误:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆