2012-03-12 27 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構造函數的方法將由引用的類型決定。

相關問題