为什么这个赋值在 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
.
的类型
我确定我可能在这里遗漏了一些相当明显的东西,但是有什么原因吗:
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
.