その理由は、Test.classのタイプがClass<Test>であるためです。Class <Test>型の参照を、Class <T>型の変数に割り当てることはできません。これらは、同じものではないためです。ただし、これは機能します。
Class<? extends Test> testType = type == null ? Test.class : type;
ワイルドカードを使用すると、Class<T>とClass<Test>の両方の参照をtestTypeに割り当てることができます。
Angelika Langer Java Generics FAQには、Javaジェネリックの動作に関する大量の情報があります。Number
クラス階層JavaのコアAPIを使用するいくつかの情報に基づいた例を提供します。
次の方法を検討してください。
public <T extends Number> void testNumber(final Class<T> type)
これは、次のステートメントを正常にコンパイルできるようにするためです。
testNumber(Integer.class);
testNumber(Number.class);
ただし、以下はコンパイルされません。
testNumber(String.class);
ここで、次のステートメントについて考えてみましょう。
Class<Number> numberClass = Number.class;
Class<Integer> integerClass = numberClass;
2行目はコンパイルに失敗し、このエラーが発生しますType mismatch: cannot convert from Class<Number> to Class<Integer>
。しかし、Integer
拡張しますNumber
、それでなぜそれは失敗するのですか?次の2つのステートメントを見て、理由を確認してください。
Number anumber = new Long(0);
Integer another = anumber;
2行目がここでコンパイルされない理由は簡単にわかります。インスタンスが互換性のあるタイプであることを保証する方法がないため、のインスタンスNumber
をタイプの変数に割り当てることはできません。この例では、は実際にはであり、これをに割り当てることはできません。実際、エラーはタイプの不一致でもあります。Integer
Number
Number
Long
Integer
Type mismatch: cannot convert from Number to Integer
互換性の保証がないため、インスタンスのタイプのサブクラスである変数にインスタンスを割り当てることはできません。
ジェネリックスも同様に動作します。ジェネリックメソッドシグニチャでT
は、は、メソッドがコンパイラに何を許可するかを示すための単なるプレースホルダーです。コンパイラーが検出するtestNumber(Integer.class)
と、基本的に。に置き換えT
られInteger
ます。
ワイルドカードは、以下をコンパイルするため、柔軟性を追加します。
Class<? extends Number> wildcard = numberClass;
これClass<? extends Number>
は、Number
またはこのサブクラスであるすべてのタイプNumber
が完全に合法であり、多くの状況で役立つ可能性があることを示しています。