为什么这个赋值在 Java 泛型中是非法的?

Why is this assignment illegal in Java generics?

我确定我可能在这里遗漏了一些相当明显的东西,但是有什么原因吗:

ArrayList<? extends Number> list = new ArrayList<Number>();

是允许的,但是:

ArrayList<T extends Number> list = new ArrayList<Number>();

不是吗?

如果您想使用像 T 这样的通用类型 class,您需要在 class 中显式声明它。 Here你可以找到官方文档。

如果您想使用未知的通配符 class,您可以在您的代码中自由使用 if here

反正你能找到类似的问题here

java 中的通用 class 应如下所示

/**
 * Generic version of the Box class.
 * @param <T> the type of the value being boxed
 */
public class Box<T> {
    // T stands for "Type"
    private T t;

    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

所以你可以使用 ArrayList<T> arr = new ArrayList<T>()

来源:https://docs.oracle.com/javase/tutorial/java/generics/types.html

因为,与:

ArrayList<? extends Number> list = new ArrayList<Number>(); //OK

您正在定义使用 上限通配符 <? extends Number>.

泛化的 ArrayList 类型的具体对象

您的通配符类型将匹配 Number 的任何 sub-type,这意味着您可以分配给 list 变量,任何 ArrayList 特化为 [=47] =]任何 类型扩展 Number:

list = new ArrayList<Float>(); //will work fine
list = new ArrayList<Double>(); //will work fine
list = new ArrayList<String>(); //will NOT work as String does not extend Number

唯一需要注意的是 Capture Problem。您将无法在列表中添加 Number extender 实例。


但是在这里:

ArrayList<T extends Number> list = new ArrayList<Number>(); //Syntax error

您的对象声明中存在语法错误。您正在使用 有界类型参数 来声明您的变量;但是,有界类型参数用于定义泛型 class/type 或泛型方法。

类型参数 T 或任何(最好是大写)字母,用于在定义 class(或方法)时声明 generic type parameter

例如,您的 upper-bounded 通用类型在此定义中:

public class YourClass<T extends Number> {
....
}

将成为真实类型,在 run-time,当你通过提供一些真实类型来声明你的 YourClass 类型时,作为泛型类型参数,如下所示:

YourClass<Integer> ints; //will work fine
YourClass<Double> doubles; //will work fine
YourClass<Float> floats; //will work fine
YourClass<String> strings; //will NOT work, as String does not extend Number

注意,这里 T extends Number 匹配任何扩展 Number.

的类型