4

このプログラムはコンパイルされません:

public class xx {
    static class Class1<C> {
        void method1(C p) {
        }
    }
    static class Class2<T> extends Class1<Class<? extends T>> {
        T object;
        void method2() {
            this.method1(this.object.getClass());
        }
    }
}

エラーは次のとおりです。

xx.java:10: method1(java.lang.Class<? extends T>) in xx.Class1<java.lang.Class<? extends T>>
cannot be applied to (java.lang.Class<capture#215 of ? extends java.lang.Object>)
        this.method1(this.object.getClass());

なぜこれが起こるのですか?なぜコンパイラはそれがではなくobject.getClass()戻ると信じているように見えるのですか?Class<? extends Object>Class<? extends T>

4

3 に答える 3

4

Tコードには上限が設定されていないため? extends T、実際には? extends Object. ちょうど昨日、私は同様の例で遊んで、この障壁にぶつかりました。私が持っていた

static <T> T newInstance(T o) throws Exception {
  final Class<? extends T> c = o.getClass();
  return c.newInstance();
}

そして、同じエラーで不平を言いました。これを考慮してください: の戻り値の型はObject.getClass()isであり、コンパイラはを具象型Class<?>にキャプチャする必要があります。?しかし代わりに、 をキャプチャするの?ではなく、「上限をキャプチャする」T必要があります。Java のジェネリックにはそのようなものはありません。

于 2012-05-24T19:56:14.103 に答える
1

Object.getClass()は、 を返すように定義されていますClass<? extends |T|>。ここTで、 はレシーバーの静的に既知の型です (オブジェクトgetClass()が呼び出されます)。縦棒である消去演算子に特に注意してください。型変数の消去は、その左端の境界の消去です。あなたの場合、それは暗黙の boundObjectです。したがって、Class<? extends Object>ではなくが返されますClass<? extends T>

何故ですか?

想像してみてください、未チェックの警告なしでT = List<Integer>突然次のことを行うことができます:

List<String> myStrings = new ArrayList<>();
List<Integer> myInts = new ArrayList<>();
List<Integer> myIntyStrings = myInts.getClass().cast(myStrings);
myIntyStrings.add(-1);
String myString = myStrings.get(0); // BANG!

しかし、ありがたいことに、警告が表示されます.. ;)

于 2012-05-24T21:32:50.883 に答える
0

getClass() のドキュメントによると、返されたオブジェクトの型は ですClass< ? extends |X| >。ここ|X|で、 はメソッドが呼び出されたインスタンスの型の消去です。

したがって、タイプのオブジェクトで getClass() を呼び出すと、Tが返されますClass< ? extends Object >Tこの API にはバインドされた情報はありません。

通常、ジェネリック クラスでリフレクションを使用する API では、クライアントが型の追加の引数をClass< T >問題のコンストラクターまたはジェネリック メソッドに渡す必要があります。

于 2012-05-24T21:21:10.977 に答える