2017-03-05 30 views
2

考慮java.util.Map接口的put方法的規範。爲什麼Map#put指定@throws ClassCastException?

它說:

@throws ClassCastException if the class of the specified key or value 
     prevents it from being stored in this map 

Map是具有兩個類型參數通用接口:KV分別用於鍵對象和值的對象。該put方法簽名是:

V put(K key, V value); 

在什麼情況下可能對這種方法的調用導致ClassCastException在運行時?

我認爲,如果有是通用的,原始類型的一些混合,再而忽略了編譯器警告可能發生這種情況。因此,重讀有效的Java 2後,我仿照unsafeAdd示例後的以下(編號23,第112):

public class MapClassCastException { 
    public static void main(String[] args) { 
     Map<Integer, String> m = new HashMap<>(); 
     unsafePut(m); 
     System.out.println(m.get(1)); 
    } 

    private static void unsafePut(Map m) { // beware: Raw Type 
     m.put("blow", "up"); 
     m.put(new int[]{2, 4}, "xxx"); 
    } 
} 

但是這個代碼失敗,在與ClassCastException運行,而不是它打印null 。 (當然,我忽略了編譯器警告只是爲了理解它)。

有人能證明如何Map#put可能會拋出一個ClassCastException在運行時? (我用JDK 1.6,1.7和1.8試了這個,他們產生了相同的結果)。

+1

用'TreeMap'試一試。 – chrylis

+0

啊,很酷。謝謝@chrylis。我忘了這個有用的'Map'實現! –

回答

1

Map是一個接口,它基本上限定該接口的所有實現的合同。 Map.put的文檔告訴你,這種方法可能會拋出ClassCastException。那並不是需要所有的實現來拋出它。

如果你看看documentation for HashMap.put,你會注意到它根本沒有提及ClassCastException。正如評論中所述,TreeMap.put確實會拋出ClassCastException,因爲它需要能夠準確比較這些密鑰。

如果你想實現自己的java.util.Map,然後你可以扔ClassCastException如果你想限制一個鍵或值的類型,即使該接口上的仿製藥不能強制執行,如果你碰巧使用原始Map類型。

我覺得這是集合API說要小心的只是執行者。

相關問題