0

このコードでコンパイラエラーが発生します:

Map<String, String[]> myMap;

void set(Map<String, Object> foo) { }

set(myMap); // generates error

Error: "The method set(Map<String,Object>) in the type XXX is not applicable for the arguments (Map<String,String[]>)"

String []は実際にはオブジェクトであり、set()のパラメーターと完全に互換性があるため、これは私には意味がありません。

このエラーは、JDK1.6から1.7にアップグレードするまでコードに表示されませんでした。Eclipseにそれをオフにするスイッチが表示されません。このコードをコンパイルするにはどうすればよいですか?

編集:

中間変数を使用するとコンパイルされ、ジェネリックが削除されます。

Map anotherMap = myMap;
set(anotherMap);
4

4 に答える 4

5

ジェネリックスの継承は、オブジェクト指向の継承に関する通常の理解とは異なります。このチュートリアルをお読みください。

コードをコンパイルするには、次のようにメソッドの構文を変更する必要があります。

void set(Map<String, ?> foo) { }

編集:dasblinkenlightがコメントしたように、setメソッド内でマップに変更を加える計画がある場合は、具体的なタイプを定義しない限り機能しません。

于 2012-10-24T21:47:23.153 に答える
1

実際String[]にはですが、それは実際には:ジェネリックの共分散Objectが存在しないと言っているのと同じではありません。Map<String,String[]>Map<String,Object>

宣言の変更

void set(Map<String,Object> foo) { }

ワイルドカード付きのものに

void set(Map<String,?> foo) { }

コードをコンパイルし、fooマップから物を取得しようとすると、次のように機能します。

Object blah = foo.get("key");

ただし、マップに物を追加しようとすると失敗します。

オブジェクトblah=foo.put( "key");

マップに物を置くことがあなたのメソッドの目標であるように見えるので(結局のところ、あなたがそれを呼んだ理由があるに違いありませんset)、正確なタイプを指定せずにそれを機能させることはできません。

于 2012-10-24T21:51:29.080 に答える
0

ジェネリックスで型パラメーターを使用する場合、継承は同じようには機能しません。

過度に単純化された一般的な経験則は次のとおりです。

<>ジェネリックオブジェクトを宣言および初期化するときは、s内のものが正確に一致する必要があります。

于 2012-10-24T21:51:12.467 に答える
0

おそらく、コンパイラのバグが原因で、Eclipseがコードをコンパイルしました。

をコンパイルするには、の署名を変更する必要がありsetますset(Map<String, ?>)

2番目のケースでは警告付きでコンパイルされますね。これは、生のマップ(ジェネリックなし)を使用して型安全性チェックを回避するためです。

于 2012-10-24T21:52:32.450 に答える