[英]Java Generics: Instantiating arrays with parameterized types: illegal?
這里我一定很困惑。
我到處都讀到,在泛型中,參數化類型的數組是非法的。
來自AngelikaLanger的示例:
static void test() {
Pair<Integer,Integer>[] intPairArr = new Pair<Integer,Integer>[10] ; // error
addElements(intPairArr);
Pair<Integer,Integer> pair = intPairArr[1];
Integer i = pair.getFirst();
pair.setSecond(i);
}
朗格的名言(但我在其他任何地方讀的都說同樣的話):
編譯器禁止創建其組件類型為具體參數化類型的數組,例如本例中的Pair。 我們在前面的條目中討論了為什么編譯器將Pair []視為非法是合理的。
到目前為止,還可以。
但是在我的代碼中:
private MyEntry<E> [] elements = (MyEntry<E>[])new Object[capacity];
我正是這樣做的,它可以很好地編譯(我使用eclipse),但是會收到類強制轉換異常錯誤(對象不能強制轉換為MyEntry):
我的問題是,為什么此行首先編譯?
我認為編譯器不允許這種實例化。
我在這里做錯/不同嗎?
更新:
在同一頁面上,我為什么能夠成功執行以下操作:
List<E> elements[] = (List<E>[])new LinkedList[capacity];
並且沒有運行時異常嗎?
更新:
我讀過的所有地方(自從被頻繁引用以來,都提到過Langer)都說編譯器不允許此聲明(參數化類型的數組)。
我可以理解之后會發生什么。
我不明白為什么編譯器不報告錯誤。
我不是在判斷,而是在閱讀的所有地方說,這不是編譯的。
我在念東西嗎?
更新:我看到一些與new
零件中缺少參數有關的注釋。
這也沒有問題:
List<Entry<KeyType, ValueType>> table[] = (List<Entry<KeyType, ValueType>>[])new LinkedList[capacity];
在第一個示例中,實例化沒有問題-這正是您要創建的內容:
new Object[capacity]
完全合法。 但是,當您嘗試進行MyEntry<E>
時,確實會遇到運行時異常,因為Object
數組不是MyEntry<E>
數組。 如果這些通用參數化的數組不存在,則可能會有一個強制轉換或聲明會被編譯器拒絕的觀點,盡管這取決於擦除的順序。無論如何,實例化本身就很好。
在第二個示例中,您將創建LinkedList
的非泛型數組。 然后,將其分配給通用引用,該引用在運行時將被刪除為List[]
。 這很好用(因為對或錯,數組是協變的)。
我不確定為什么會遇到運行時異常。 跟打電話說沒什么不同
List<E> = new LinkedList();
您會得到一些未經檢查的警告,但是沒有什么會阻止代碼的編譯或運行。
因為LinkedList
是List
的實例。 但是Object
不是 MyEntry
的實例。 同樣,編譯器不會檢查是否可以將一個對象強制轉換為另一個對象。 因為它是運行時操作。
您應該使用:
private MyEntry<E> [] elements = new MyEntry [capacity];
要么:
class SomeOtherEntry extends MyEntry {}
private MyEntry<E> [] elements = new SomeOtherEntry [capacity];
但不是:
class SomeOtherEntry extends MyEntry {}
private SomeOtherEntry <E> [] elements = new MyEntry [capacity];
更新:
List<Entry<KeyType, ValueType>> [] table = (List<Entry<KeyType,ValueType>> []) new Linked[capacity];
您已經完全誤解了所讀的內容。 具有參數化類型的數組的類型絕對沒有錯: MyEntry<E>[]
或HashMap<String,Integer>[][]
或其他任何東西。 您可以隨意擁有所有此類類型的變量,並在可以使用任何類型的地方使用它們。
但是,使用數組創建時,您無法執行new MyEntry<E>[...]
。 該語言不允許這樣做(出於類型安全的原因,我們將不在此處介紹),因此它是編譯錯誤。
最好的解決方案是new MyEntry[]
(原始類型的數組)或new MyEntry<?>[]
(通配符類型的數組); 語言允許任何一種。 他們兩個都需要您顯式地轉換回MyEntry<E>[]
。
由於您詢問的是代碼示例,因此您的第一個示例在語法上是正確的( new Object[...]
沒錯,並且在語法上也可以MyEntry<E>[]
轉換為MyEntry<E>[]
),因此沒有編譯錯誤。 但是, MyEntry[]
類型MyEntry[]
的運行時檢查在運行時失敗,因為對象的實際類型Object[]
不是MyEntry[]
的子類型。
第二個代碼示例在語法上也是正確的,並且強制轉換的運行時檢查成功( LinkedList[]
是 List[]
的子類型)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.