2012-01-02 6 views
3

いくつかの複雑なJavaのジェネリックではgetClass()を使用している場合:アイデアは、あなたがに変換するタイプAのメッセージを持っているということですコンパイル型の不一致私はこのインタフェースを持つメソッド持って

public <A extends Message, B extends Message> MessageConverter<A, B> 
    getDefaultConverterFor(Class<A> inputClass, Class<B> outputClass); 

をタイプBのメッセージであり、使用可能な登録済みコンバーターのリポジトリーからそれを行うように変換プログラムを取得したいとします。残念ながら、私はこのタイプのどちらかのタイプを期待どおりに動作させるのに苦労しています。

public <M extends Message> Message convert(M m) 
{ 
    MessageConverter<M, DictMessage> converter = 
     getDefaultConverterFor(m.getClass(), DictMessage.class); 

    return converter.convert(m);     
} 

(すなわち任意の型のメッセージを取り、DictMessageに変換)が、それはgetDefaultConverterライン上で私にコンパイルエラーを与える:

具体的

、私はこれをやろうとしています

Type mismatch: cannot convert from MessageConverter<capture#1-of ? extends Message,DictMessage> to MessageConverter<Message,DictMessage>". 

なぜこのようなことが起こるのか、それを修正する方法はわかりません。私はgetClassによって返されたクラスがMとまったくマッチしないクラスと関係があると思いますが、実際には分かりません。私はこれが実際にはうまくいかない可能性があると信じることができましたが、それを破る特定の例は考えられません...思考?

答えて

1

私はしばらくの間Class<?>を返すObject.getClass()に問題がありました。コンパイラはm.getClass()Class<M>であることを知りませんが、キャストで修正できます。

@SuppressWarnings("unchecked") 
MessageConverter<M, DictMessage> converter = 
     getDefaultConverterFor((Class<M>) m.getClass(), DictMessage.class); 
1
public <M extends Message> Message convert(M m) { 
    Class<M> abc = m.getClass(); // compile error 
    ... 
} 

動作しません。

getClass()コールの前に型キャストを追加できます。

public <M extends Message> Message convert(M m) { 
    Class<M> abc = (class<M>)m.getClass(); // ok 
    ... 
} 

またはあなたの方法に追加のクラス・パラメータを追加することができます。

public <M extends Message> Message convert(M m, Class<M> mClass) { 
    // use mClass instead of m.getClass() 
    ... 
} 

それとも、あなたのMessageConverter変数の型パラメータを変更することができます。

public <M extends Message> Message convert(M m) { 
    MessageConverter<? extends Message, DictMessage> converter = this.getDefaultConverterFor(m.getClass(), DictMessage.class); 

JavadocのためのgetClass()戻り値をは:

The java.lang.Class object that represents the runtime class of the object. 
The result is of type Class<? extends X> where X is the erasure of the static 
type of the expression on which getClass is called. 

したがって、返品タイプgetClass()Class<? extends Message>で、Class<Message>ではありません。

1

以下は完全に型指定されています。

public class MessageConverter<INP extends Message, OUTP extends Message> { 
    private Class<INP> inputClass; 
    private Class<OUTP> outputClass; 

    public MessageConverter(Class<INP> inputClass, Class<OUTP> outputClass) { 
     this.inputClass = inputClass; 
     this.outputClass = outputClass; 
    } 

    public OUTP convert(INP m) { 
     try { 
      return outputClass.newInstance(); 
     } catch (InstantiationException | IllegalAccessException ex) { 
      throw new IllegalStateException(ex); 
     } 
    } 
} 

public <INP extends Message, OUTP extends Message> MessageConverter<INP, OUTP> 
     getDefaultConverterFor(Class<INP> inputClass, Class<OUTP> outputClass) { 
    MessageConverter<INP, OUTP> mc = new MessageConverter<INP, OUTP>(inputClass, outputClass); 
    return mc; 
} 

public <INP extends Message> MessageConverter<INP, DictMessage> 
     getDictConverterFor(Class<INP> inputClass) { 
    MessageConverter<INP, DictMessage> mc = 
      new MessageConverter<INP, DictMessage>(inputClass, DictMessage.class); 
    return mc; 
} 
関連する問題