次のコードを指定します。
public static void main(String[] args) {
HashMap<String, String> hashMap = new HashMap<>();
HashMap<String, Object> dataMap = new HashMap<>();
dataMap.put("longvalue", 5L);
class TestMethodHolder {
<T> T getValue(Map<String, Object> dataMap, String value) {
return (T)dataMap.get(value);
}
}
hashMap.put("test", new TestMethodHolder().<String>getValue(dataMap, "longvalue"));
String value = hashMap.get("test"); // ClassCastException occurs HERE
System.out.println(value);
}
このコードがコンパイルされることは驚くべきことではありませんが、ClassCastException がその上の put 行ではなく get 行で発生することは驚くべきことではありません。ジェネリック型は実行時に消去されるため、getValue() でのキャストは実際には実行時に発生せず、事実上 Object へのキャストです。メソッドが以下のように実装される場合、ランタイム キャストが発生し、put 行で失敗します (予想どおり)。誰でもこれを確認できますか?
class TestMethodHolder {
String getValue(Map<String, Object> dataMap, String value) {
return (String)dataMap.get(value);
}
}
これは、ジェネリックを使用することの既知の欠陥または奇妙ですか? メソッドを呼び出すときに <> 表記を使用するのは悪い習慣ですか?
編集: デフォルトの Oracle JDK 1.7_03 を使用しています。
上記からのもう 1 つの暗黙の質問: 元の getValue のキャストは実行時にまだ発生していますが、キャストは実際には Object に行われていますか? またはコンパイラは、実行時にこのキャストがまったく発生しないように削除するのに十分スマートですか? これは、ClassCastException が発生している場所の違いを説明している可能性があります。