1

次のコードを検討してください。

public class Generics {
    C c; // initialized at runtime

    public void testGenericsCall(Object o) {
        c.myMethod(o);
    }
}

class C<E> {
    public void myMethod(E input) {
    }
}

これは機能していますが、パラメータ化されたクラスCがraw型で使用されているため、警告が表示されます。私は次のような宣言を使用できません

C<String> c;

Cのタイプは実行時にのみ認識されるためです。また、Cの型を知る前にこのクラスのオブジェクトを作成する必要があるため、Genericsクラスに型パラメーターを追加することはできません。宣言

C<?> c;

また

C<? extends Object> c;

コンパイラーにとっては問題ありませんが、メソッドtestGenericsCallはコンパイルされません(「実際の引数java.lang.Objectは、メソッド呼び出し変換によって?のキャプチャ#1に変換できません」

このような状況に対処するための最良の方法は何ですか?

編集:私が実際に(実行時に)Cのインスタンスを作成するとき、その型パラメーターを知っていることに注意してください。コードのこの部分は型セーフであり、うまく機能しています。実際のコードでは、単一の「C」クラスはありませんが、一連の相互に関連するクラスがあり、ジェネリックは間違いなく便利です(この単純化された例では、これは明らかではありません。したがって、単に教えないでください)私はジェネリックを使用しないでください:)。私はすでにコンパイル時の型安全性を持っていますが、ここではありませんが、Cと他のクラス(ここには示されていません)の間です。

この場合、コンパイル時にtypeパラメーターをチェックできないことがわかります。そのため、宣言しようとしました C<?> c。ここでは、コンパイラの警告なしにジェネリックコードと非ジェネリックコードをブリッジするための最良の方法を探しています。

4

2 に答える 2

3

タイプ eraserのため、実行時にジェネリックを使用する方法はありません。型などをチェックして、プログラムでデータ型を処理する必要があります (おそらくリフレクション)。

于 2013-02-19T10:56:26.843 に答える
2

あなたはそれを行うことができます。しかし、汚いトリックと反省を通して。たとえば、以下のコードを見てください。ここでの礼儀:

class ParameterizedTest<T> {

/**
 * @return the type parameter to our generic base class
 */
@SuppressWarnings("unchecked")
protected final Class<T> determineTypeParameter() {
    Class<?> specificClass = this.getClass();
    Type genericSuperclass = specificClass.getGenericSuperclass();
    while (!(genericSuperclass instanceof ParameterizedType) && specificClass != ParameterizedTest.class) {
        specificClass = specificClass.getSuperclass();
        genericSuperclass = specificClass.getGenericSuperclass();
    }
    final ParameterizedType parameterizedType = (ParameterizedType) genericSuperclass;

    final Type firstTypeParameter = parameterizedType.getActualTypeArguments()[0];
    return (Class<T>) firstTypeParameter;
}



}

//change the type of PrameterizedTest<Integer> to Parameterized<String> or something to    display different output
public class Test extends ParameterizedTest<Integer>{
 public static void main(String... args){
    Test test = new Test();
    System.out.println(test.determineTypeParameter());
}

}

ここでは、ランタイムで型パラメーターを取得します。したがって、代わりにクラスで、Class上記で説明したようにクラスを取得するオブジェクトを定義する必要があります。次にClass.newInstance、新しいオブジェクトを取得します。ただし、型キャストなどは手動で処理する必要があります。

問題は次のとおりです。これはすべて価値がありますか??

ジェネリック型で境界を使用し、バインドされた型にインターフェースすることでほとんどを回避できるため、私によればいいえ

于 2013-02-20T06:12:29.220 に答える