ArrayListの配列を作成しようとすると、なぜArrayList<Integer>[] arr=new ArrayList<Integer>[40];
エラーが発生し、Javaはこれを許可しないのですか?
ジェネリックのJavaの実装、任意の言語のジェネリック、または任意の何かに関連する理由はありますか?
ArrayListの配列を作成しようとすると、なぜArrayList<Integer>[] arr=new ArrayList<Integer>[40];
エラーが発生し、Javaはこれを許可しないのですか?
ジェネリックのJavaの実装、任意の言語のジェネリック、または任意の何かに関連する理由はありますか?
回答:
これはJavaのジェネリックスの主要な穴の1つです。配列は共変です。つまり、型の配列Foo[]
はObject[]
andのサブクラスですParentOfFoo[]
。これとList<Foo>
は異なり、この動作はありません。
これは、Javaにジェネリックがなかった場合(Java 5まで)に重要でした。
ただし、実行時に配列がどの型であるかを知りたいというこのトリッキーな問題があります。ただし、Javaのジェネリックスは型消去に基づいています。これらの2つはうまくメッシュ化されず、そこで問題が発生します。
つまり、Java 1では、共変配列がジェネリックの欠如によって生じた穴を部分的に埋めていました。ただし、この穴を適切に埋めようとしたときに、下位互換性のために配列を実装することはかなり不可能でした。
実際、ジェネリックのフレームワークを実際に作成した人であるMartin Oderskyは、なぜScalaを作ったのかについてのインタビューで、これについてここで話しました。(Scalaの歴史にまったく興味があるなら、かなり魅力的です)
ジェネリックのJavaの実装、任意の言語のジェネリック、または任意の何かに関連する理由はありますか?
実際、それはやや恣意的です。
問題は、型システムに穴を開けることができることです。これは、ArrayList<T>[]
にキャストObject[]
できArrayList<U>
、配列にを配置できるためU != T
です。
Java設計者たちは、このホールをまったく許可new ArrayList<T>[N]
しないことで、できる限り積極的にこの穴を塞ぐことにしました。
ただし、ジェネリックの配列のアップキャストを許可しないことでプラグインされている可能性もあります(「チェックされていない」警告なし)。
Integer
にObject[]
実際だString[]