我充分認識到通用陣列不能像這樣被實例化:爲什麼我允許將一個泛型數組聲明爲一個實例變量?
data = new Entry<K, V>[];
這將導致一個錯誤:
Cannot create a generic array of Entry<K,V>
那麼,爲什麼我允許聲明一個實例變量,它是一個泛型類型的數組沒有錯誤?
private Entry<K, V>[] data;
我充分認識到通用陣列不能像這樣被實例化:爲什麼我允許將一個泛型數組聲明爲一個實例變量?
data = new Entry<K, V>[];
這將導致一個錯誤:
Cannot create a generic array of Entry<K,V>
那麼,爲什麼我允許聲明一個實例變量,它是一個泛型類型的數組沒有錯誤?
private Entry<K, V>[] data;
原則,約阿希姆·紹爾的評論已經是你的答案,不過,我想詳細了一點。
太陽(甲骨文)知道的被叫存儲器污染現象,如果一個通用變量指針指向其總是會發生到類型不兼容的對象。這可以被強制執行,例如用下面的代碼:
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想要的:如果可能發生污染,則會發出警告。
因爲編譯器和/或JIT需要能夠推斷泛型類型。
當您嘗試創建Entry<K, V>[]
的實例時,編譯器無法推斷出類型K和V,因此您將無法創建實際對象(這意味着編譯器無法找到正確的構造函數)。
但是,如果你有Entry<K, V>[]
類型的成員,它只是一些泛型類型的引用。
根據分配給它的實際類型,使用它時會推斷出正確的類型。而且因爲它引用了一個實際類型,所有調用anc構造函數的方法將由引用的類型決定。
聲明泛型類型的數組中,幾乎只有* *聲明使用它是這樣的你*意向*。由於編譯器*不能*檢查通用類型,並且您可以*輕鬆*使用數組中的泛型類型來破壞類型系統,編譯器會在您執行無法檢查的操作時告訴您。最佳解決方案:當您希望編譯器檢查您的類型一致性時,避免使用數組。 – 2012-03-12 07:33:05
又見安格莉卡朗格[泛型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