5

以下のコード スニペットがあり、これは正常に動作します。オブジェクトを含むものとして定義cしたが、オブジェクトを追加しているため、コンパイル時エラーをスローすべきではありません。では、なぜコンパイル時/実行時エラーをスローしなかったのでしょうか?ArrayListStringInteger

Collection c = new ArrayList<String>();
c.add(123);

以下はコンパイル時エラーをスローすることを知っていますが、なぜ上ではないのですか。これらのコード スニペットの論理的な違いは何ですか?

 Collection<String>() c = new ArrayList();
 c.add(123);
4

4 に答える 4

6

最初のコード スニペットはコンパイル時エラーにはなりません。

c.add(123)

コンパイラは c の型を検査します。c をCollectionとして宣言したため、コンパイラはそれをそのように扱います。メソッドを提供するため、c に対する任意のオブジェクト、特に整数に対して完全に合理的です。ただし、コレクション値を文字列として読み戻そうとすると、このプログラムは実行時エラーになることに注意してください。Collectionadd(Object)add

2 番目のコード スニペットでは、コンパイラが処理するための詳細情報を提供します。このスニペットでは、処理する が であり、 のみを受け入れることができることがわかってCollectionCollection<String>ますStrings。したがって、メソッドadd(int)orはなくadd(Object)、 のみadd(String)です。これにより、コンパイル時エラーが発生します。

于 2013-01-06T13:31:37.127 に答える
3

なぜコンパイル時エラーをスローしなかったのですか?

構文的にも意味的にも無効ではないため、賢明ではありません。

ほとんどの最新の IDE (Eclipse など) は、パラメータ化されていない について警告しCollection c、オプションでコンパイルに失敗するように構成できることに注意してください。

于 2013-01-06T13:28:25.197 に答える
0

最初の例では、コレクションは「生」です。これは通常、警告になりますが、エラーにはなりません (正確な設定によって異なります)。これは、Java 5 より前のすべてのレガシー コードをコンパイルできるようにするための主要な方法です。

2 番目の例では、"生の" オブジェクトをパラメーター化されたバージョンに割り当てます。これは、明示的なキャストでのみ行うことができます。

于 2013-01-06T13:32:33.213 に答える
0

1) 論理的な違いは何ですか?

上: Collection はジェネリック型なしで宣言できます。これはraw タイプと呼ばれます。コレクションは、あらゆる種類のコレクションを保持できます。生の型付きコレクションでは、実行時に文字列のコレクションを整数のコレクションとして使用する可能性があるため、ランタイム例外が発生し、コンパイラは通常警告をスローします。上記の例ではコレクションを入力していないため、コンパイラはこれらの実行時例外を防ぐことができません。警告の目的と実行内容がわかっている場合は、警告を無視できます。

下: ただし、Collection<String> として宣言された変数は、どのような種類のコレクションも保持できません。タイプ String のコレクションである必要があります。ストロングタイプです。コンパイラはこれをエラーとして認識します。

2) 上記のスニペットでコンパイラ エラーが発生しないのはなぜですか?

Java は厳密に型指定されているため、型の安全性が保証されます。上記のスニペットはタイプ セーフではありませんが、Java では許可されています。これはおそらく歴史的な理由によるものです。ジェネリックは Java 1.5 でのみ導入されたため、上記のスニペットがコンパイル エラーを引き起こした場合、ほとんどの Java 1.4 コードは Java 1.5 コンパイラで壊れていたでしょう。

すべてのプログラミング言語がこのように下位互換性を保って進化しているわけではありません (たとえば、PHP)。Java 1.5 の導入時には、型の安全性よりも下位互換性が重視されたようです。

于 2013-01-06T13:35:31.283 に答える