[英]Why <T> for toArray hides <E> of Collection<E>?
toArray
方法隱藏<E>
傳遞給Collection<E>
接口。 以下是方法簽名。
<T> T[] toArray(T[] a);
因為以下是可能的。 並將結果轉換為ArrayStoreException
ArrayList<String> string = new ArrayList<String>();
string.add("1");
string.add("2");
Integer intArray[] = new Integer[2];
intArray = string.toArray(intArray);
我想知道為什么會做出這樣的決定? 為什么在設計API時允許這樣的情況? 無論如何,這段代碼會導致RuntimeException
?
toArray
方法早於泛型的引入。 toArray
的原始簽名采用了任意Object[]
。
這是泛型的唯一方法,即接受泛型之前允許的相同輸入。 但是,采用任意T[]
的優點是它可以返回它傳遞的相同數組類型。
當你調用時, intArray = string.toArray(intArray);
,你期望它構造Integer
數組並返回值,因此在你的情況下返回類型是T[]
即Integer[]
。
調用這樣的方法並不意味着你能夠自動將String list轉換為Integer []
。 上面的方法調用將導致java.lang.ArrayStoreException
。
這樣做是為了允許使用可轉換類(基類/子類),例如:
List<Integer> list = new ArrayList<Integer>();
list.add(1);
Integer[] intArray = new Integer[1];
intArray = list.toArray(intArray); //Success
Number [] numArray = new Number[1];
numArray = list.toArray(numArray);//Success
Double [] dubArray = new Double[1];
dubArray = list.toArray(dubArray); //Failure(ArrayStoreException)
當你問自己toArray()
數組的類型應該是什么時,第一個最明顯的方法是將T
限制為E
的超類型(包括如果T
與E
相同):這是有道理的 -能夠將元素復制到比我們的集合更通用的元素類型的數組。 但是,雖然這看起來是類型安全的(即在編譯時檢查,因此在運行時沒有異常發生)乍一看,它不是完全類型安全的 - 類型T[]
的變量可以包含任何類型U[]
數組U[]
其中U
是的子類型T
。 因此,即使我們將T
限制為E
超類型( 即使我們將T
限制為與E
相同),仍然可以獲得ArrayStoreException
。 另外,很難以這樣的方式聲明這個方法,即T
只能是E
的超類型,因為Java不允許類型參數的super
邊界。
問題中的示例涉及T
不是E
的超類型。 為什么要允許這樣做? 這不是類型安全的,只有當集合的元素實際上是數組實際類型的子類型時才有效。 然而,可以認為這仍然不比我們將T
限制為E
的超類型的情況,或者即使我們將T
與E
相同,因為如上所述,這些限制都不能使它成為也是類型安全的。 無論您如何聲明此方法,都可能獲得ArrayStoreException
。 那么,為什么不盡可能地讓它變得一般,如果不是更糟糕呢?
string.toArray(intArray)
返回String
類型的String
; 但是,你希望它是一個Integer
類型的數組。 這將返回您提到的異常,由於類型不匹配而導致ArrayStoreException
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.