1

として宣言されているが としてインスタンス化さIntegerれている Java 配列にを追加しようとすると、コンパイル エラーが生成されないのはなぜですか?Object[]String[]

Object[] ob = new String[1];
ob[0] = new Integer(1); // this shouldn’t compile but it does!

これを実行すると、(非常に好ましい) コンパイル時エラーではなく、実行時例外が発生します! これは正しい動作ですか?コンパイル時エラーは発生しませんか?

4

2 に答える 2

3

Java 設計者が行った選択: String[]extendsですが、実行時例外を取得せずに具象型がである配列にObject[]a 以外のものを追加することはできません。StringString[]

彼らが無効にした可能性があるのは次のとおりです。

Object[] ob = new String[1];

整数オブジェクトであり、コンパイル時の配列の型はObject[].

彼らは配列に対してこの選択をしませんでしたが、ジェネリック コレクションに対しては選択しました。

List<Object> ob = new ArrayList<String>();

List<String>は を拡張しないため、コンパイラ エラーが発生しますList<Object>。コレクションは、より安全で、より多くの機能を提供するため、通常は配列よりも優先されます。

于 2012-07-01T17:45:38.287 に答える
2

考慮すべき主な点は、参照される配列の実行時の型 ( String[]) と配列変数のコンパイル時の型 ( Object[]) です。コンパイラは、配列に入れられたものが、それを参照する配列変数の静的型と互換性があることのみを強制します。この例はそれを際立たせます:

String[] strs = new String[1]; 
Object[] objs = strs; 
strs[0] = new Integer(1); /* error, says the compiler! */ 
objs[0] = new Integer(1); /* fine by me, says the compiler! */

さて、正当に腹を立てる必要があるのは、実際には最初の行です。Object[] ob = new String[1];これは、それString[]が代入互換性があることを意味しますObject[]— つまり、そのサブタイプです。これは、コンテナ型がその要素の型において反変であるという CS のよく知られた事実とは対照的です。では、なぜJavaではそうではないのでしょうか? James Gosling に尋ねられたアカウントを読んだことがあります。彼は事実を認識していると答えましたが、Java メソッドが任意の種類の配列を (Object[]型を介して) 受け入れることができるようにする簡単な方法が必要でした。これは、Java が「ブルーカラー言語」であり、独自の精神的な荷物をもたらす型理論の厳密さには入らないという要件に起因しています。ジェネリック<? super String>と Scala の共変/反変の位置規則を確認します。

于 2012-07-01T18:46:44.410 に答える