我得到一個ClassCastException當Eclipse建議,我的代碼應該是這樣的..ClassCastException異常時日食「固定」我的代碼
我有一個名爲科爾特類。
ArrayList<Kort> kort = new ArrayList<Kort>();
然後我用toArray()
和Eclipse建議它應該看起來像:Kort[] array = (Kort[])kort.toArray()
;
但它給了我這個例外:ClassCastException! :(
我得到一個ClassCastException當Eclipse建議,我的代碼應該是這樣的..ClassCastException異常時日食「固定」我的代碼
我有一個名爲科爾特類。
ArrayList<Kort> kort = new ArrayList<Kort>();
然後我用toArray()
和Eclipse建議它應該看起來像:Kort[] array = (Kort[])kort.toArray()
;
但它給了我這個例外:ClassCastException! :(
你可以做的是:
Kort[] array = kort.toArray(new Kort[kort.size()]);
這被認爲是更好,因爲它使陣列上的類型安全。如果你不在乎/希望如果沒有參數,toArray()方法返回一個Object []數組。
使用
kort.toArray(new Kort[kort.size()]);
我的建議是:
kort.toArray(new Kort[0])
從技術上講,這可能比給出正確的大小要慢一些。但是,您不需要提及集合變量名稱兩次,因此出錯的可能性較小。這也更容易閱讀。作爲獎勵,它也適用於併發集合,在那裏調用size
並不真正具有很大的意義。
但是,最好的方法是避免使用引用數組,如果可能的話。
有趣的是默認IDEA會給你一個這樣的語法警告,所以我已經習慣了指定尺寸,但是你是對的,它是一個微型優化,顯然不是一個好的方法 – Yishai 2009-10-20 01:15:24
問題的根源在於java.util.Collection
API中的Object[] toArray()
和Object[] toArray(Object[])
方法之間的差異。
第一種形式分配正確大小的數組來保存集合的成員,然後將成員引用分配到數組中。由於集合類不知道實際成員的類型(請參見下面的註釋),API指定結果爲Object[]
的實例;即如同使用new Object[size]
分配一樣。
第二種形式將一個數組作爲參數,它將(通常)成爲存儲集合成員引用的參數。因此,程序通過傳遞所需類型的數組來確定結果的類型。如果提供的數組足夠大以容納收集元素,則方法將返回提供的數組實例。如果不是,則爲所提供的數組實例分配一個新的數組。 (這可以通過使用Array.newInstance(clazz, size)
其中clazz
是提供的數組的組件類沉思完成的。需要注意的是類型參數不是用來做這個...它不能使用。)
所以發生的是,Eclipse是不足夠聰明地知道,真正糾正你的錯誤是使用不同的方法過載。爲了進行這種修正,它需要「知道」兩種形式的方法的具體語義。這是一個高難度的海事組織。
經驗教訓是,Eclipse的建議更正只是建議......並不保證是正確的修復。
注意:由於類型擦除,集合類不知道要在toArray()
情況下創建的適當數組類。有關類型如何實例化的信息不適用於實現toArray
的類。但考慮到通常可以插入Collection<T>
而不是T
(通過忽略「不安全類型」編譯器警告),這可能是好東西結果類型是Object[]
!
此問題早於泛型類型;自從在Java 1.2中引入集合框架以來,這種方法的兩種形式就已經存在了。
編輯:在評論@Thilo建議,如果Java從一開始就支持泛型,就不會出現這個問題。我的回答是,它不是這樣發生的,我們不能說如果他們有的話會發生什麼。但我們可以說,與Java的泛型,因爲他們目前定義這是不可能的,沒有重新設計集合的API。
具體而言,泛型類無法確定實際類型已被用作給定實例的類型參數。沒有這些信息,它就無法知道要實例化的正確數組類型。在實踐中,如果您希望泛型類型創建類型參數或某些相關類型的實例,則必須設計API,以便相關方法可以運行時訪問實際參數類型的對象Class
。例如,實際的Class對象可以作爲構造函數參數提供。
至少toArray ()方法只需要一個類對象並創建數組本身,即使使用類型擦除。它可以確保類對象是集合的正確類型,如toArray(類 super T>類型); – Yishai 2009-10-20 23:41:23
@義海 - 同意了,但這與現有的[
的
kort.toArray(new Kort[kort.size()]);
在
(Kort[])kort.toArray();
的是,在情況下,你地圖集合爲空,將所得到陣列應的對象類型的零長度陣列將拋出異常另一個優點如果改爲Kort。
使用kort.toArray(new Kort[kort.size()]);
可確保即使集合爲空仍然返回的數組是所需的類型。
FYI ...如果您在代碼行的開頭添加四個空格,Markdown會將這些字符放入「代碼格式」中,您的<>將顯示出來。 – karlgrz 2009-10-19 21:26:32