List<String> a1; ArrayList<Object> a2; ArrayList<? extends Object> a3;
こんな感じでListに関する変数が三つ定義されてるとします。さて、以下でコンパイルエラーになるのはどれ?
// 初期化 a1 = new ArrayList<String>(); a2 = new ArrayList<String>(); a3 = new ArrayList<String>(); // メソッド呼び出し a1.add("hoge"); a2.add("hoge"); a3.add("hoge");
なかなかわかりにくい挙動だと思うんですよねえ。。。o(゜^ ゜)
初期化はa2がエラーになります。Generic型が違う場合、たとえそれが継承関係でもキャストすらできません。主にセッターの事情だと思うんですが、a2の代入文を許してしまうと、このオブジェクトの内部に別の型*1を放り込むことが簡単に出来てしまい、型の一貫性が取れなくなります。
メソッド呼び出しはa3がエラーになります。a3は、例えば、IntegerをGeneric型とするArrayListである可能性もあるからです。
*1:Objectクラスを継承するもの全てOKなので