0

サービス インターフェイスに@Serviceアノテーション (Spring ではなくカスタム アノテーション) が付けられているプロジェクトがあり、サービスごとに複数の実装 (hibernate、mongodb など) が存在する可能性があります。

次のようなリフレクションを使用して実装クラスをロードしようとしています。

@Serviceステップ 1:アノテーション付きのすべてのインターフェースをロードする

ステップ 2: 各インターフェースのすべてのサブクラスをロードする

コードは次のとおりです。

public static void main(String[] args) throws Exception{
    Reflections reflections = new Reflections("net.jitix.cfs");
    //load annotated interfaces
    Set<Class<?>> types=reflections.getTypesAnnotatedWith(Service.class);

    Iterator<Class<?>> typeIterator=types.iterator();

    typeIterator.forEachRemaining(new Consumer<Class<?>>() {

        @Override
        public void accept(Class<?> type) {
            if(!type.isInterface()){
                typeIterator.remove();
            }
        }
    });

    for(Class<?> type:types){
        //load implementation classes
        Set<Class<?>> implTypes=reflections.getSubTypesOf(type); //error here
    }

    //rest of the code
}

私が得ているコンパイルエラー:Type mismatch: cannot convert from Set<Class<? extends capture#8-of ?>> to Set<Class<?>>

私の理解 Class<?>によると、型は何でもかまいません。そのため、必要なメソッドがパラメーターとしてとれない理由がわかりClass<T>ません。Class<?>

なぜこれが起こっているのかを理解してくれる人はいますか?私のアプローチに代わるものはありますか?前もって感謝します!

編集:@MGorgonによるコメントと@StriplingWarriorおよび@Sotirios Delimanolisによる回答によると、反射法を使用することは問題外です。型の参照を持つ型のサブ型を取得する方法はありますかClass<?>

4

2 に答える 2

2

この質問の核心は反射とは何の関係もありませんが、むしろ共分散/反分散です。それは効果的です:

Set<? extends Something>をに代入できないのはなぜSet<?>ですか?

そして答えは、もしあなたが を持っていればSet<?>、コンパイラはあなたがそのセットに任意の型 (例えば ) のオブジェクトを追加できるようにXし、誰かが元の値からその値を取得しようとすると、あなたがそうSet<? extends Something>することが判明したときに実行時エラーが発生するということです。X 伸びません Something

この原理は、次のようにさらに簡単に示すことができます。

Set<Dog> dogs = getDogs();
Set<Pet> pets = dogs;        // the compiler will complain here
pets.add(new Cat("Fluffy")); // to avoid letting this happen
for(Dog dog : dogs)         // which would cause an exception here
{
   ...
}

ただし、このセットに何も追加する予定がないことは (おそらく) わかっているので、少し明示的なキャストを使用して、自分が何をしているのかを知っていることをコンパイラに伝えるのがおそらく安全です。

Set<Class<?>> implTypes= (Set<Class<?>>)(Set<?>)reflections.getSubTypesOf(type);
于 2014-08-26T22:13:59.560 に答える
1

getSubTypesOfメソッドは次のように宣言されます

public <T> Set<Class<? extends T>> getSubTypesOf(final Class<T> type) {

Tこれは、型パラメーターとして宣言するジェネリック メソッドです。メソッドを呼び出すと、暗黙的に、または明示的に指定されたために、メソッド呼び出しによって型引数がキャプチャされます。

type の引数を指定してメソッドを呼び出しましたClass<?>?メソッドはas タイプをキャプチャします。したがって、メソッドの戻り値の型は になりますSet<Class<? extends CAP of ?>>。特定の不明なタイプのサブタイプである、不明なタイプのクラスのセット。

Set<Class<?>>ただし、未知のタイプのクラスのセットである にそれを割り当てようとしています。しかし、その未知の型は、必ずしも特定の未知の型のサブタイプであるとは限りません。大声で言うとあまり意味がないことはわかっていますが、?orCAP of ?を特定のタイプと考えてください。これは、やろうとしているのと同じです

Set<Class<?>> implTypes = new HashSet<Class<Integer>>();

Classfinalであり、したがってサブクラス化できないため、これはすぐにはわかりませんが、 a が a にHashSet<Class<Integer>>代入できないSet<Class<?>>のと同じように、 aArrayList<ArrayList<Integer>は に代入できませんList<List<?>>

追加資料:

于 2014-08-26T22:21:32.290 に答える