2016-05-17 4 views
0

問題が発生しました。私は解決策を見つけることができませんでした。ジェネリックスのワイルドカードはGenerictypeにキャストできません

私はしばしば、キーと値が一致するgenerictypesを持つオブジェクトであるマッピングを利用します。各ペアについて、ジェネリックが一致する必要があります。エントリー間のgenerictypesはバリエーションがあるかもしれません。 (明確にするために例が含まれています)。 これは、ワイルドカードを使用して簡単に実行できます。このため、キーや値を組み合わせて使用​​することはできません。

下の例を考えてみましょう。キャスト例外に実行するようにマップを変更する(簡単な)方法はありません。私はまだuseEntries()のように地図を使うことができません。だから私の質問は、これのための回避策はありますか?前もって感謝します!

public class GenericWildcardTest 
{ 
    static Map<GenericObject<?>, Function<?, ?>> map = new HashMap<>(); 

    public static <S> void put(GenericObject<S> genericObject, Function<S, S> function) 
    { 
     map.put(genericObject, function); 
    } 

    public static void useEntries() 
    { 
     for(Entry<GenericObject<?>, Function<?, ?>> currentEntry : map.entrySet()) 
      //The #apply(); part simply wont compile because of cast errors. 
      currentEntry.getKey().set(currentEntry.getValue().apply(currentEntry.getKey().get())); 
    } 



    // Simple Object with generic. 
    static class GenericObject<T> 
    { 
     private T object; 

     public GenericObject(T object) 
     { 
      this.object = object; 
     } 

     public void set(T object) 
     { 
      this.object = object; 
     } 

     public T get() 
     { 
      return this.object; 
     } 
    } 
} 
+0

キャスティングは明らかな回避策です。 – shmosel

+0

私はあなたの記事とあなたの質問に混乱しています。ジェネリックスとワイルドカードを使用しています。このチュートリアルでは、ジェネリックスとワイルドカードを完全にカバーし、あなたの問題を明らかにすることをお勧めします。 [Java™チュートリアル:ジェネリックス(更新済み)](http://docs.oracle.com/javase/tutorial/java/generics/index.html) – Underbalanced

+0

@shmoselあなたは、これをキャストしようとしなかったのですか?それは働かないからです。私はそれ自身のジェネリック実装でプライベートメソッドを作成しようとしました。それはむしろ単純です。 generictypeはワイルドカードにキャストできますが、バイカバーはキャストできません – n247s

答えて

2

は、あなたが鋳造でそれを行うことができます方法は次のとおりです。

@SuppressWarnings("unchecked") 
public static <S> void useEntries() { 
    for(Entry<GenericObject<?>, Function<?, ?>> currentEntry : map.entrySet()) { 
     GenericObject<S> key = (GenericObject<S>)currentEntry.getKey(); 
     Function<S, S> value = (Function<S, S>)currentEntry.getValue(); 
     key.set(value.apply(key.get())); 
    } 
} 

この答えはあなたのマップが実際にFunction<S, S>、ないFunction<GenericObject<S>, S>含まれていることを前提としています。

+0

私は、誤ってチェックされていないキャストを追加しないように、メソッド全体ではなく、キャストごとに個別に抑制を置くことを好みます(たとえば、@SuppressWarnings(...)GenericObject key = ...)後でメソッドを変更した場合。しかし一般的に、これは生の型よりはるかに優れたアプローチです。@AndyTurner、 –

+1

が合意した。私は実際に一歩進んで、 'T 'を公開しないようにプライベートメソッドを作成します(実際は単一のタイプを表します)。しかしここでは簡単な方法をとることにしました。 – shmosel

0

次のようにuseEntriesメソッドを書き換えることができます:メソッド内GenericObjectFunctionからジェネリック医薬品を削除

@SuppressWarnings("unchecked") 
public static void useEntries() { 
    for (Map.Entry<GenericObject<?>, Function<?, ?>> currentEntry : map.entrySet()) { 
     GenericObject key = currentEntry.getKey(); 
     Function value = currentEntry.getValue(); 
     key.set(value.apply(key.get())); 
    } 
} 

あなたは純粋なObjectインスタンス上の呼び出しを行うことができます。正しいタイピングを保証するのはあなたの責任です。注釈SuppressWarningは、それ以外の場合に出力されるコンパイル警告を削除します。ここで

+0

それは考えられませんでした。愚かに単純です。ありがとう – n247s

+2

生のタイプを使用しないでください:キャストを使用してください。 –

+1

cast before raw typesをお勧めします。実際にこのコードには、生の型のために見落とされるバグがあります。 – shmosel

関連する問題