北海道苫小牧市出身の初老PGが書くブログ

永遠のプログラマを夢見る、苫小牧市出身のおじさんのちらしの裏

Generic型と継承

	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なので