2017-01-31 2 views
1

を確保これに沸くasourceから来る消費者:Javaは、私は2つのオブジェクトがO1取得同じワイルドカードキャプチャタイプ

public interface MySource<T> { 
    Class<T> getType(); 

    Consumer<T> getComsumer(); 
} 

私はバックの両方を想定し、一般的な方法にそれらを餌にしたいです同じタイプ(パラメータ)を持つこと。

public interface Registry<M> { 
    <T extends M> void register(Class<T> type, Consumer<T> consumer); 
} 

どこからでも、私は未知のタイプのMySourceを取得します。

Javaは、実在する型が実際に同じであるということを推論するほどスマートではありません。

public abstract class Example<M> { 
    Registry<M> registry; 

    static MySource<? extends M> getSrc(); 

    public <T extends M> void register(Class<T> type) { 
     MySource<? extends M> src = getSrc(); 
     registry.register(src.getType(), src.getComsumer()); 
    } 

> The method register(Class<T>, Consumer<T>) in the type 
> Registry<M> is not applicable for the arguments 
> (Class<capture#3-of ? extends M>, Consumer<capture#4-of ? extends M>) 

別のオブジェクトに結果をラップする必要がありますか?または、これを解決するためのより良い方法がありますか?

+0

あなたは 'MYSOURCE 'の代わりに、別々に渡す必要がありますように見えますパラメータは、2つの異なることはできません。 –

+2

'registry.register(...)'への呼び出しを含む完全なメソッドまたはクラス、特にメソッド宣言またはクラス宣言(型パラメータがありますか?)を表示します。 – Jesper

+0

@AndyTurner:私はそれが問題を解決するだろうが、私のアーキテクチャでは意味をなさないでしょう。 – IARI

答えて

1
は、周りのあなたの境界を回し

MySource<M> src; 
Registry<? super M> registry; 

次に、あなたのregistry.register(src.getType(), src.getComsumer());がうまく動作します。

あなたは少しラッパー・メソッドがそれをやりたいかもしれません。そして、

<M> void wrapRegister(MySource<M> src, Registry<? super M> registry) { 
    registry.register(src.getType(), src.getComsumer()); 
} 

MySource<? extends M> src = ...; 
Registry<M> registry = ...; 
wrapRegister(src, registry); 

Ideone demo

+0

@Jesperが要求したように、私は最小限のクラスでアプリケーションをラップしました。必要に応じて、それに応じて回答を調整することができます。 – IARI

+0

私は質問された質問に答えました。私はあなたの動くゴールポストを追いかけたくありません。 –

+0

謝罪 - ゴールポストを動かすことが何を意味するのか正確には分かりませんが、元の投稿からの質問は変更されていません:要求されたとおり、明快にするためにアプリケーションをクラスにラップしました。 私はそれが、この回答を受け入れるならば、あなたの時間を無駄にするつもりはないが、この投稿に絡み合っている人に役立つかもしれないと想像しました。 – IARI

0

はい、確かに、Javaは十分にスマートではありません。ただし、反射を使用してメソッドを呼び出すことができます。

try { 
    Method registerMethod = registry.getClass().getMethod("register", Class.class, Consumer.class); 
    registerMethod.invoke(registry, src.getType(), src.getConsumer()); 
} catch (Exception e){ 
    e.printStackTrace(); 
    // generics didn't match or something else went wrong, you can catch specific Exceptions from reflective .invoke() method 
} 

これはすべきことです。

+0

ありがとうございます - 可能ならば、私は反射を避けてみたいと思います。私のための他の選択肢がない場合、私はこの解決策に頼ります。 – IARI

+0

Reflectionはこれに対する良い解決策ではありません。コンパイラは理由の型チェックをしています。それを避けているだけでなく、 'Registry.register(Class、Consumer)'メソッドの存在のチェックを避けています。リフレクションよりも生の型を使う方が良いでしょう。少なくとも、コンパイラはメソッドの存在をチェックします。しかしどちらかを使う必要はありません。 –

関連する問題