2017-03-05 2 views
2

インターフェイスのputメソッドの仕様を検討してください。Map#putが@throws ClassCastExceptionを指定するのはなぜですか?

それは言う:それぞれのキーオブジェクトと値オブジェクトのためのKV

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

Mapは2つの型パラメータとの一般的なインタフェースです。 putメソッドシグネチャは次のとおりです。どのような条件の下で

V put(K key, V value); 

は、このメソッドの呼び出しは、実行時にClassCastExceptionを引き起こす可能性がありますか?

コンパイラの警告を無視して、一般的な種類と生の種類が混在している場合は、この問題が発生する可能性があります。だから、効果的なJavaの2を再読み込みした後、私は(。アイテム#23頁112)unsafeAdd例の後に次のようにモデル化:

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"); 
    } 
} 

しかし、このコードはではなく、それはnullを印刷し、ClassCastExceptionと実行時に失敗しません。 (もちろん、私はコンパイラの警告を無視して、それをよく理解するだけです)。

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.putClassCastExceptionをスローします。なぜなら、キーを正確に比較できる必要があるからです。

あなたがjava.util.Map独自のものを実装したい場合は、キーまたは値の種類を制限したい場合、あなたはその後、インターフェイス上のジェネリック医薬品は、あなたが起こる場合は、生のMapを使用するようにすることを強制することはできませんにもかかわらず、ClassCastExceptionを投げることができタイプ。

私はこれがCollections APIの実装者にすぎないことを慎重に言っていると思います。

関連する問題