Home > Java > なぜ Java の配列は共変で、Generics は共変ではないのか

なぜ Java の配列は共変で、Generics は共変ではないのか

まず、Java の配列がタイプセーフではない話。

public class ExampleArray {

    public static void main(String[] args) {
        String[] strArray = {"test1", "test2"};
        Object[] objArray = strArray; // 配列は共変なので代入可能

        objArray[0] = new Integer(3); // java.lang.ArrayStoreException
    }
}

上記のように、Java の配列は共変という性質を持っているので、Object[] に String[] を代入することができます。つまり、String[] は Object[] のサブクラスである、ということです。
しかし、Generics の場合は、この性質が当てはまりません(Generics は共変ではない)

public class ExampleGenerics {

    public static void main(String[] args) {
        List<String> strList = new ArrayList<String>();
        strList.add("test1");
        strList.add("test2");

        List<Object> objList = new ArrayList<Object>();

        objList = strList; // コンパイルエラー
    }
}

なぜ、配列は共変で、Generics は共変ではないのか?(一緒の方が分かりやすいのに)

その理由の前に、
配列の例で見たように、型の混入現象は、強い型付け言語である Java としては避けたい現象です。
配列の場合は、不正な型が混入した場所で例外(java.lang.ArrayStoreException)を投げてくれます。
(これは、結構大事な所で、使用時(get)ではなく、設定時(set)にきちんと例外を投げてくれると、バグの混入場所が特定しやすいです)
なぜこんなことができるかというと、配列は自分が何の型であるかを自身で知っている(バイトコードに型情報が存在する)ので、違う型を入れたときに、自分と違うということが判定できるのです。

一方、Generics の場合はコンパイル時に型消去という操作が行われます。
型消去については、別エントリーでも書いてます(Generics(Java)の型消去について

Generics のコードは、コンパイル後にはその型情報を一切残していないので、java.lang.ArrayStoreException のような例外を投げることができません。
そのため、共変ではなくして、型の混入を防いでいるのではないかと思います。

Generics で共変っぽいことをしたい場合は、extends とかの境界条件をつければ可能です。

Comments:1

bleis-tift 2013年4月23日

配列が共変なのは、Genericsがなかった時の名残です。
配列が共変になっていないと、例えばArrays.sort(Object[])などは定義できません。
Genericsが最初からJavaにあれば、配列は共変ではなく(Genericsの場合と同じく)不変とされていたでしょう。
その方が、コンパイル時により多くのエラーを発見できます。

Comment Form
Remember personal info

Trackbacks:1

Trackback URL for this entry
http://sinsengumi.net/blog/2011/12/%e3%81%aa%e3%81%9c-java-%e3%81%ae%e9%85%8d%e5%88%97%e3%81%af%e5%85%b1%e5%a4%89%e3%81%a7%e3%80%81generics-%e3%81%af%e5%85%b1%e5%a4%89%e3%81%a7%e3%81%af%e3%81%aa%e3%81%84%e3%81%ae%e3%81%8b/trackback/
Listed below are links to weblogs that reference
なぜ Java の配列は共変で、Generics は共変ではないのか from sinsengumi血風録
pingback from Javaでは配列よりリストを選ぶ ‹ 技術の犬小屋 2015年3月30日

[...] 今まで知らなかった 5 つの事項: Java コレクション API の場合: 第 1 回 なぜ Java の配列は共変で、Generics は共変ではないのか – sinsengumi血風録 [...]

Home > Java > なぜ Java の配列は共変で、Generics は共変ではないのか

Search
Feeds
Meta

Return to page top