2011-05-17 79 views
2

以下代碼將在toArray()處拋出ArrayStoreException。假如toArray需要V[]並且註冊表Map鍵入的值爲Map<String,String>,那麼編譯器是否應該沒有發現錯誤並報告了類型衝突?編譯器是否應該在泛型集合中發現這個錯誤?

private Map<String,Map<String,String>> registry; 

... 

registry=new TreeMap<String,Map<String,String>>(String.CASE_INSENSITIVE_ORDER)); 

... 

void removeTargets(String[] clsarr, String hdl) { 
     if(clsarr==null) { clsarr=registry.values().toArray(new String[0]); } 
    ... 
    } 

它看起來像一個編譯器bug。

回答

3

不是編譯器錯誤。可以說是一個圖書館的錯誤。

Collection.toArray()的類型是<T> T[] toArray(T[] a)。請注意,TtoArray方法的類型參數,與Collection的類型參數沒有任何關係。

這個bug會被抓如果Collection.toArray簽名是<T super E> T[] toArray(T[] a)但是這將使它很難使用,因爲它是不合法的做new Map<String, String>[0] - 你得到一個「通用陣列創建」的錯誤。

+0

再一次,仿製藥的支持「總比沒有好,但留下了許多不足之處」。感謝您的解釋。 – 2011-05-17 20:14:36

+0

@軟件猴子。是啊。廣泛使用的編程語言中的類型系統存在漏洞,導致錯誤可能漏過。這不是由於任何理論上的限制,而是由於Java數組類型的早期設計,它決定通過說'String []'是一個Object []'來解決方差問題,這使得它很難工作類型到試圖正確處理差異的泛型類型系統中。 – 2011-05-17 20:31:02

2

號的toArray函數爲:

<T> T[] toArray(T[] a)

返回包含此集合中的元素的陣列;返回數組的運行時類型是指定數組的運行時類型。

其中通用集合中的類型是E。所以你可以傳入任何類型的變量。

這是一個klunky的設計,因爲通用類型在編譯時被擦除,所以在運行時無法返回適當類型的數組。這就是爲什麼你必須提供toArray呼叫中的類型。海事組織這是相當不雅 - 傳遞你想要的類型的數組 - 但Java並沒有在這裏提供任何方式來提供類型註釋。