簡體   English   中英

Java泛型:使用參數化類型實例化數組:非法嗎?

[英]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();

您會得到一些未經檢查的警告,但是沒有什么會阻止代碼的編譯或運行。

因為LinkedListList的實例。 但是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM