境界ワイルドカードと代入互換性
型パラメータの「境界ワイルドカード」を使用すると、条件を満たす型パラメータを持つオブジェクトを代入可能な変数を作ったりできますが、境界ワイルドカードを持つ型を型パラメータ内で使うとやはり代入互換性は失われてしまいます。
// 型パラメータ指定付きのList同士は、たとえパラメータの型に代入互換性があっても // 代入互換性はない。(「Genericsは共変でない」とかいうらしい。) List<String> strs = null; List<Object> objects = null; //objects = strs; // コンパイルエラー // これはもちろんOK Object obj = null; String str = null; obj = str; // OK // 同様に、型パラメータの境界ワイルドカードを使用した場合も、 // 素では代入互換性があっても、 // 型パラメータとして使うと、代入できなくなってしまう。 Class<String> class1 = null; Class<?> class2 = null; class2 = class1; // OK List<Class<String>> classList = null; List<Class<?>> classList2 = null; // classList = classList2; コンパイルエラー
↓みたいな関数があって、
// 任意のクラスのリストを受け取る関数 static final void test( List<Class<?>> list ) {}
↓のように呼び出そうとして、今日もしばらくはまってしまった・・orz。
List<Class<String>> array = null; // 省略 test( array ); // コンパイルエラー
この場合、以下が正解。
// 任意のクラスのリストを受け取る関数 static final void test( List<? extends Class<?>> list ) {}