4

これは、 Java Genericsを使用してやろうとしていることの単純化されたサンプルです。

void <T> recursiveMethod(T input) {
    //do something with input treating it as type T
    if (/*need to check if T has a supertype*/) {
        recursiveMethod((/*need to get supertype of T*/) input);

        // NOTE that I am trying to call recursiveMethod() with
        // the input object cast as immediate supertype of T.
        // I am not trying to call it with the class of its supertype.
        // Some of you seem to not understand this distinction.
    }
}

タイプA extends B extends C (extend Object)の長いチェーンがある場合、呼び出しrecursiveMethod(new A())は次のように実行する必要があります。

recursiveMethod(A input)
 -> A has supertype B
recursiveMethod(B input)
 -> B has supertype C
recursiveMethod(C input)
 -> C has supertype Object
recursiveMethod(Object input)
 -> Object has no supertype -> STOP

次のようにジェネリックなしでそれを行うことができます:

void recursiveMethod(Object input) {
    recursiveMethod(input.getClass(), input);
    }
}

private void recursiveMethod(Class cls, Object input) {
    //do something with input treating it as class 'cls'
    if (cls != null) {
        recursiveMethod(cls.getSuperclass(), input);
    }
}

ジェネリックを使用して同じことを行うことはできますか? as として宣言してから as として<S, T extends S>キャストしようとしまし(S)inputSが、常に等しいためTスタック オーバーフローが発生します。

4

2 に答える 2

3

問題を解決できる反復アプローチを次に示します。

public static <T> void iterateOverSupertypes(T input) {
    Class<?> clazz = input.getClass();
    while (clazz.getSuperclass() != null) {
        clazz = clazz.getSuperclass();
    }
}
于 2013-08-30T08:39:02.320 に答える
2

新しい A を作成してコード内で渡すと、何をしてもオブジェクトは常に A のままになります。

キャストやジェネリクスなどは、期待するオブジェクトのクラスをコンパイラに伝える唯一の方法ですが、オブジェクトの動作を変更することはありません。したがって、「型Tとして扱う」ことで何を達成しようとしているのかわかりませんが、これを達成する唯一の方法は、ジェネリックなしの例で行ったように型を渡すことです。

PS: 常に覚えておいてください: Java ジェネリックは、コンパイラが型安全性を確保するための手段にすぎませんが、コンパイルされたコードにはそれらの痕跡はありません!!!!

于 2013-08-30T09:00:55.697 に答える