ユーザ用ツール

サイト用ツール


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