java:covariant
共変(covariant)
共変の戻り値
Java5からメソッドをオーバーライドするとき、戻り値の型を変更することが可能になった。
共変戻り値はcloneメソッドで最もよく利用される。
public interface Cloneable{ public Object clone(); } public class CloneableImpl implements Cloneable{ public CloneableImpl clone() { try { return (CloneableImpl)super.clone(); } catch (CloneNotSupportedException e) { throw new InternalError(e.getMessage()); } } }
CloneableImplはObjectの一つであるので、CloneableImpl clone();
はObjectを返しているのと同義つまり、このメソッドはObject clone();
と同等であると言える。
配列とcovariant
配列はcovariantである。IntegerはNumberであり、Integer[]はNumber[]である(共変)
Number[] n = new Integer[]{ 1, 2, 3 }; // Integer[]は、Number[]であるので代入できる。 n[0] = Double.valueOf(0d); // コンパイルエラーにならないが実行時例外(ArrayStoreException)
これはJava言語設計の失敗とも言われている。covariantは戻り値のようにgetするものに対しては安全だが、setする場合に危険。
ジェネリクスとcovariant
配列の反省を受けて(?)ジェネリクスはcovariantではない。IntegerはNumberであるが、List<Integer>はList<Number>ではない。
ArrayList<Number> i = new ArrayList<Integer>(); // コンパイルエラー
これは以下のようなコードを許可しないためと思われる
ArrayList<Number> i = new ArrayList<Integer>(); i.add(Long.valueOf(1));
配列では以下のソースがコンパイル可能で、実行時エラーになる。
Number[] i = new Integer[1]; i[0] = Long.valueOf(1); // 実行時エラー(ArrayStoreException)
java/covariant.txt · 最終更新: 2011/06/23 06:02 by nullpon