我完全清楚泛型数组不能像这样实例化:
data = new Entry<K, V>[];
这将导致错误:
Cannot create a generic array of Entry<K,V>
那么,为什么我可以声明一个没有错误的泛型类型数组的实例变量?
private Entry<K, V>[] data;
答案 0 :(得分:4)
原则上,Joachim Sauer的评论已经是你的答案,但是,我想稍微详细一点。
Sun(Oracle)知道一种称为内存污染的现象,如果泛型变量指针指向类型不兼容的对象,则会发生这种现象。例如,可以使用以下代码强制执行此操作:
List<String> list = new ArrayList<String>();
List<Number> numberList = (List<Number>)(List)list;
显然,一旦开始使用该代码,您将开始看到ClassCastExceptions
。在设计Generics时,这对Sun来说完全没问题,因为您会收到强制警告RawType / Unchecked转换。无论何时发出此警告,您都知道您拥有的代码不是100%类型检查的,并且可能会发生内存污染。
泛型中的总体设计原则是,所有可能的记忆污染都由这种警告表示。这就是为什么禁止创建通用数组的原因。假设不是,那么可能会发生这种情况:
List<String>[] array = new List<String>[5];
Object[] oArray = array // this works without warning and has to for compatibility
List<Object> oList = new ArrayList<Object>();
oArray[1] = oList;
在没有任何警告的情况下,您将有内存污染,并且出于兼容性原因,无法生成警告。这就是为什么Sun决定禁止泛型类型的数组。但是,可能会声明变量,因为您在那里获得了未经检查的转换警告,而这正是Sun想要的:如果可能发生污染则发出警告。
答案 1 :(得分:2)
因为编译器和/或JIT需要能够推断泛型类型。
当您尝试创建Entry<K, V>[]
的实例时,编译器无法推断出类型K和V,因此您将无法创建实际对象(这意味着编译器无法找到正确的构造函数)。
但是,如果你有Entry<K, V>[]
类型的成员,它只是对某些泛型类型的引用
根据将分配给它的实际类型,将在使用时推断出正确的类型。因为它引用了一个实际类型,所有调用anc构造函数的方法都将由引用的类型决定。