2012-03-12 25 views
8

我充分认识到通用阵列不能像这样被实例化:为什么我允许将一个泛型数组声明为一个实例变量?

data = new Entry<K, V>[]; 

这将导致一个错误:

Cannot create a generic array of Entry<K,V> 

那么,为什么我允许声明一个实例变量,它是一个泛型类型的数组没有错误?

private Entry<K, V>[] data; 
+3

声明泛型类型的数组中,几乎只有* *声明使用它是这样的你*意向*。由于编译器*不能*检查通用类型,并且您可以*轻松*使用数组中的泛型类型来破坏类型系统,编译器会在您执行无法检查的操作时告诉您。最佳解决方案:当您希望编译器检查您的类型一致性时,避免使用数组。 – 2012-03-12 07:33:05

+0

又见安格莉卡朗格[泛型FAQ](http://www.angelikalanger.com/GenericsFAQ/FAQSections/ParameterizedTypes.html#Can%20I%20create%20an%20array%20whose%20component%20type%20is%20a%20concrete% 20instantiation%20of%20A%20parameterized%20type?) – McDowell 2012-03-12 09:57:52

回答

4

原则,约阿希姆·绍尔的评论已经是你的答案,不过,我想详细了一点。

太阳(甲骨文)知道的被叫存储器污染现象,如果一个通用变量指针指向其总是会发生到类型不兼容的对象。这可以被强制执行,例如用下面的代码:

List<String> list = new ArrayList<String>(); 
List<Number> numberList = (List<Number>)(List)list; 

很明显,你将开始看到ClassCastExceptions,一旦你开始使用该代码的工作。 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想要的:如果可能发生污染,则会发出警告。

2

因为编译器和/或JIT需要能够推断泛型类型。

当您尝试创建Entry<K, V>[]的实例时,编译器无法推断出类型K和V,因此您将无法创建实际对象(这意味着编译器无法找到正确的构造函数)。

但是,如果你有Entry<K, V>[]类型的成员,它只是一些泛型类型的引用。
根据分配给它的实际类型,使用它时会推断出正确的类型。而且因为它引用了一个实际类型,所有调用anc构造函数的方法将由引用的类型决定。

相关问题