1

引数の1つとしてクラスオブジェクトを必要とする別のメソッドを呼び出すメソッドを持つジェネリッククラスがあります。オブジェクト作成時にジェネリックとして設定されているクラス型を使用できるようにしたいのですが、構文が正しくないようです。これが私がやりたいことです:

public abstract class GenericClass<T> {

    private void doStuff() {
        //do a bunch of stuff

        //This method's signature is methodToCall(Serializable s) and is not a method I can change
        methodToCall(T);
        methodToCall(Class<T>);
        methodToCall(T.class);

        //do some more stuff
    }

}

public class NonGenericClass extends GenericClass<DesiredClass> {

}

Classオブジェクトタイプはシリアル化できるため、これは機能します。

methodToCall(DesiredClass.class);

しかし、メソッドの途中でクラス型が必要になるため、すべてのコードをコピーしてしまうため、メソッドを簡単にオーバーライドすることはできません。

これが私がこれまでに思いついた最高のものです:

public abstract class GenericClass<T> {

    protected abstract void doStuff();

    protected <T> void doStuff(Class<T> cls) {
        methodToCall(cls);
    }

}

public class NonGenericClass extends GenericClass<DesiredClass> {

    @Override
    protected void doStuff() {
        doStuff(DesiredClass.class);
    }

}

それは機能しますが、ジェネリッククラスはTが何であるかについての知識を無駄にしているように感じます。methodToCall最初にリストした3つのバージョンの呼び出しに構文エラーがありますか?これはどうしてもできないことですか?

これがすべて理にかなっていることを願っています。

4

3 に答える 3

2

パラメータが任意の型を実装するメソッドを呼び出す場合は、ジェネリック型を確認し、Tその型を実装/拡張する必要があります。

public class GenericClass<T extends Serializable>
{
    // ...
}
于 2012-10-11T15:09:07.617 に答える
2

GenericClass実行時型トークンが必要です。Class<T>オブジェクトがコンストラクターに渡され、フィールドに保存されます。コードはあなたの最善の試みとほぼ同じくらい冗長ですが、より標準的です:

class GenericClass<T> {

    Class<T> clazz;

    public GenericClass(Class<T> c) {
        clazz = c;
    }

    protected void doStuff() {
        methodToCall(clazz);
    }

}
于 2012-10-11T15:21:51.563 に答える
0

この場合、オブジェクトの実際のランタイムクラスが常にGenericClass実際のクラスを型引数として実装することがわかっている場合は、クラスのメタデータからその型引数を取得できます(ここでは実際のクラスを想定しています)GenericClass検索を簡素化するために、の直接のサブクラスです):

private void doStuff() {
    Class<T> clazz = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    methodToCall(clazz);
}
于 2012-10-12T01:45:22.637 に答える