public class foo<T> {
protected T[] arr;
public foo() {
T[] f = new T[5];
}
}
我有两个问题:
&#34;无法创建T&#34;的通用数组,我为T[] f = new T[5];
收到此错误。为什么我不能创建通用数组?
如果不可能,为什么我向通用数组声明引用?我没有因为取消而导致编译错误:protected T[] arr;
答案 0 :(得分:0)
为什么我不能创建通用数组?
你需要了解一些事情:
T
将编译为Object
,如果<T extends SomeType>
将变为SomeType
,确保运行时阵列的安全性需要记住它可以容纳的元素类型。换句话说,它记得这个
new ElementType[size];
^^^^^^^^^^^
在运行时,您可以尝试使用不同类型的引用来保存某个对象。例如,如果你有课程
abstract class Fruit{}
class Apple extends Fruit{}
class Banana extends Fruit{}
你可以使用
Fruit[] fruits = new Apple[10];
并且因为fruits
被视为Fruit
编译器的数组,将允许您编写
fruits[0] = new Apple();
但也
fruits[0] = new Banana();
因为fruits
也可以容纳Banana
数组(出于同样的原因,它现在可以容纳Apple
数组),但正如您所看到的那样Banana
不是Apple
所以你需要一种机制来防止你用不合适的元素破坏你的数组
因此,在将元素放入数组时,它执行测试以检查元素类型是否相同或创建数组时使用的类的子类型。
此机制不适用于
T[] f = new T[5];
因为在运行时此代码看起来像
Object[] f = new Object[5];
这意味着数组会让你存储任何类似于过大风险的元素,因此Java创建者不会让编译器接受这种代码。
为什么我向通用数组声明引用?
由于一些原因,但主要是因为是一种在没有反射帮助的情况下创建T
类型数组的方法。
如果您使用
T[] t = (T[])Array.newInstance(componentType, size);
您将创建componentType
类型的数组。 componentType
必须是代表通用Class
类型的T
的实例。换句话说,我们的代码看起来像
class foo<T> {
protected T[] arr;
@SuppressWarnings("unchecked")
public foo(Class<T> componentType) {
arr = (T[]) Array.newInstance(componentType, 5);
}
}
你可以像
一样使用它foo<String> f = new foo<String>(String.class);
// ^^^^^^^^^^^^ class literal