2017-07-31 6 views
0

私はMap<K, V>を持っていて、それはMap<K, U>にキャストしたいところです。VUになります。例:Map<String, String>からMap<String, Object>に行きたい。この問題は、あらゆる種類のコレクションに存在します。地図をスーパークラスジェネリックタイプのマップにキャスト

This questionには、「ハッキー」ソリューションの回答と、一般的なタイプのキャストが一般的に悪い理由が説明されています。しかし、のはVOOからの回答から例を再訪してみましょう:

List<String> m = Something; 
m.add("Looks good."); 
m.add("42"); 
List<Object> s = (List<Object>)m; // (1) does not compile 
List<Object> t = (List)m; // (2) compiles with warnings 
Object myObject = s.get(1); 

この例についていくつかの質問:

  • なぜこれが(1)コンパイルされませんか?ハック(2)以外のコンパイル方法ですか?
  • List<String>List<Object>にキャストすると、すべての文字列がオブジェクトなので、何が問題になる可能性がありますか?
  • 私の具体的な問題

私はレベルごとにマップが含まれているMap<Integer, Map<Vector2i, MyClass> > map = ...を持っています。レベル0のマップのタイプはMap<Vector2i, MySubClass> special = ...です。今度はspecialがキー0のmapの一部になりたいので、キー0のmapへのアクセスを通常のMap<Vector2i, MyClass>オブジェクトとして扱うことができます。

状況は読み取り専用です。つまり、mapspecialへの書き込みは別々に行われます。

+0

多分この回答は役に立ちます:https://stackoverflow.com/questions/4288084/how-to-convert-liststring-to-listobject –

+0

私は興味があります*なぜあなたはそのキャストが必要だと思いますか?これはXY問題かもしれません。 – shmosel

答えて

1

一覧<オブジェクト>に<文字列>を一覧にキャストする場合、すべての文字列はオブジェクトであるため、おそらく間違って何をして行くことができますか?

このような観点から見てください:List<Object>の場合は、すべてを追加できます。

List<Object> t = (List)m; // (2) compiles with warnings 
t.add(1235); // it's a List<Object>, so we can add an Integer 

for (String s : m) { // m only contains Strings, right?! 
    System.out.println(s.length()); 
} 

をそして、あなたは予想通りStringないClassCastExceptions一度ヒットます:だから、これは例えば、間違って行くことができます。

[補足]

なぜこれは(1)コンパイルしないのですか?ハック(2)以外のコンパイル方法ですか?

実際の問題は何であるか分かりませんので、私はちょうど推測しています。

/* Just example; functionality does not matter, just that it accepts List<Number> */ 
public static void printNumbers(List<Number> numbers) { 
    numbers.forEach(System.out::println); 
} 

上のユーティリティメソッドがList<Number>を取り、ちょうどそれらのそれぞれを出力します。しかし、私は同様の問題に直面した最初の時間は、このようなものでした。現在、コードにList<Integer>List<Double>などがあります。しかし、次のコードはコンパイルノードになります。今

public static void printNumbers(List<? extends Number> numbers) { 
    numbers.forEach(System.out::println); 
} 

:(あなたはもちろんの架空のユーティリティメソッドを管理している場合など)の代わりに野生の鋳造を行うので、今

List<Integer> integers = Arrays.asList(1, 2, 3); 
printNumbers(integers); 

を、次の手順を実行しますこの方法は、Numberの任意の種類のListを受け入れます。しかし、実際の型は実行時には分かっていないので、メソッド内のリストには何も追加できません(null)。

この説明はおそらく少しカジュアルです。詳細を知りたい場合は、「PECSルール」(「プロデューサ拡張、コンシューマスーパー」)を検索します。もちろん、Mapなどの一般的なタイプにも同じことが適用されます。

+0

私は参照してください。私は '読書'の部分に焦点を当てて、完全に物事を混乱させることが可能であることを書くことを完全に忘れていました。 – piegames

+0

もう1つの追加事項は、 '型消去'の概念であり、ジェネリックはコンパイル時の概念です。キャストは 'List s =(List )List.class.cast(m);'を実行することによって実行時に実行できますが、それはPandoraのボックスです。特別な見識については、https://stackoverflow.com/questions/14524751/cast-object-to-generic-type-for-returning –

+0

を参照してください。私の問題を解決する解決策、ありがとう。 – piegames