1

次のシナリオを考えると

class Base { }
class Extended extends Base {}

ジェネリック型のサブクラスであるジェネリック クラスのコンストラクターで、クラス オブジェクトを簡単に要求できます。

class Test<T extends Base> {
  Test(Class<? extends T> test) { }
}

このようにして、次のすべてを行うことができます

new Test<Base>(Base.class);
new Test<Base>(Extended.class);
new Test<Extended>(Base.class); // This is not allowed by the compiler
new Test<Extended>(Extended.class);

まさに私が欲しいものです。ただし、次のような一般的なメソッドを使用すると、同じ制約をどのように達成できるかわかりません。

<T extends Base> void test(T x, Class<? extends T> test) { }

この定義により、次のすべてがコンパイラによって許可されます。

test(new Base(), Base.class);
test(new Base(), Extended.class);
test(new Extended(), Base.class); // even though Base is not a subclass of Extended
test(new Extended, Extended.class);

これは、型推論とJavaの決定によるものだと思います

<Base>test(new Extended(), Base.class)

それ以外の

<Extended>test(new Extended(), Base.class)

しかし、後者の推論方法を強制するにはどうすればよいでしょうか?

手伝ってくれてありがとう!

将来の読者のために: この質問の最初のバージョンでは、Base AExtended B. 後でこの表記法を明確にしました。ただし、この表記は回答で使用されます。

4

4 に答える 4

0

OK、これを 2 つの部分に分けて試します。まず、呼び出し元は常にスーパークラスをジェネリックとして指定し、サブクラスを最初の引数として渡すことができるため、あなたが望むことはできないと思います。

第二に、これをコンパイル時のチェックにしようとするのは間違ったアプローチだと思います。なぜなら、ユーザーは常に生の型を使用することを選択し、すべてのジェネリックを無視する可能性があるからです。これを実行時のチェックにして、適切なドキュメントを提供する必要があります。

于 2013-06-25T12:01:03.937 に答える
0

ジェネリックは、任意の「制限」を課すためのものではありません。ジェネリックスは型の安全性のみを目的としています。つまり、安全でないキャストを回避します。あなたが提示する制限を持つタイプセーフな理由はありません。タイプセーフになる関数testはありませんが、そうではありません。test(new Base(), Base.class);test(new Extended(), Base.class);

于 2013-06-26T07:42:42.220 に答える
-1

答えは、最初のケースではジェネリック型を指定することだと思います: new Test<B>(...). に注意して<B>ください。ただし、2 番目のケースでは、ジェネリック型を指定しません。test(a, A.class)したがって、コンパイラが動作するジェネリック型を決定できるかどうかを確認できるようにします。の場合、test(b, A.class)はのインスタンスである<A>ため動作します。bA

次のようなものを試してください:myInstance.<B>test(b, A.class)

于 2013-06-25T11:46:04.877 に答える