最初の行は機能するが、2番目の行は機能しないのはなぜですか。
Class<? extends Class> c1 = (new Object()).getClass().getClass();
Class<? extends Class<? extends Class>> c2 = (new Object()).getClass().getClass().getClass();
最初の行は機能するが、2番目の行は機能しないのはなぜですか。
Class<? extends Class> c1 = (new Object()).getClass().getClass();
Class<? extends Class<? extends Class>> c2 = (new Object()).getClass().getClass().getClass();
のAPIドキュメントからObject.getClass
実際の結果タイプはClasswhere|X|です。getClassが呼び出される式の静的型の消去です。
したがって(new Object()).getClass()
、を返しますClass<? extends Object>
。それを呼びかけますgetClass
。したがって、XはになりますClass
。これにより、が得られClass<? extends Class>
ます。
Type mismatch: cannot convert from Class<capture#5-of ? extends Class> to
Class<? extends Class<? extends Class>>
それが理由です。ここで生のタイピングが壊れているように見えます。ジェネリックスは、コンパイル中にそのタイプが削除されます。必要な型キャストを追加すると、再び機能します
Class<? extends Class<? extends Class>> c2 =
(Class<? extends Class<? extends Class>>) (newObject()).getClass().getClass().getClass();
Javaは型消去を使用します。そのようなものはありません
Class<? extends Class<? extends Class>>
実際には、しかありませんClass<?>
。他のすべては仮想です。
これで、3つのジェネリックExample<G1, G2, G3>
を持つクラスのオブジェクトは、実行時に型であることが保証されるだけですExample<?,?,?>
。ジェネリックは実行時に消去され、それgetClass()
が評価されることを忘れないでください。
ArrayList<Integer> inta = new ArrayList<Integer>();
ArrayList<Double> doua = new ArrayList<Double>();
System.err.println(inta.getClass() == doua.getClass());
を返す必要がありtrue
ます。したがって、getClass()
も同じタイプである必要がありますClass<ArrayList<?>>
。外側のタイプは既知であり、実行時に使用できます。ジェネリックは消去されました。
プログラミングエラーを回避するために、次のタイプをキャストできます。
Class<ArrayList<Double>> dacls = (Class<ArrayList<Double>>) doua.getClass();
ただし、それでも整数配列リストと同じクラスになります。