2013-01-06 22 views
5

以下のコードスニペットがあり、これは問題なく動作します。私はStringオブジェクトを含むArrayListとしてcを定義したのでコンパイル時エラーが発生しませんが、Integerオブジェクトを追加しています。だから、なぜそれはコンパイル時間/実行時エラーをスローしていないのですか?ジェネリックで宣言されたこのコレクションでエラーはありませんか?

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

私が知っているのは、コンパイル時のエラーですが、それ以上の理由はありません。これらのコードスニペットの論理的な違いは何ですか?それは時間のコンパイルエラースローしなかった理由

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

最初に '' rawtypes "'という警告を出すべきです。コンパイラに注意してください。コードリントを無料で保つことは良い考えです。 –

答えて

6

c.add(123) 

で、コンパイラはCのタイプを検査するので、最初のコードスニペットは、コンパイル時エラーが発生しません。 cをCollectionと宣言しているので、コンパイラはそのように扱います。 Collectionはメソッドadd(Object)を提供するので、addの任意のオブジェクト、特に整数には全く合理的です。ただし、このプログラムになると、コレクション値を文字列として読み取ろうとすると実行時エラーが発生することに注意してください。

2番目のコードスニペットでは、コンパイラが動作するための詳細情報を提供します。このスニペットでは、それが扱うCollectionCollection<String>であることがわかります。これはStringsしか受け入れられません。したがって、方法はありませんadd(int)またはadd(Object)add(String)のみです。これにより、コンパイル時エラーが発生します。

+0

OPの最初のスニペットは正常に動作します。 'Integer'を' String'として読み込もうとするまで、実行時エラーは発生しません。 –

+0

@Alexander理想的には実行時エラーはありませんか? – emilly

+0

私はそれがあるだろうと思っていただろうが、彼自身の答えに対する@ OliCharlesworthのコメントによれば、それはそうではないようだ。私は1つにすることを好むだろうが、明らかにJavaはそう考えていない:) –

3

構文上または意味上無効ではないので、それは賢明ではありません。

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

+0

Well Oliは、Stringオブジェクトを含むはずのArrayListを宣言していますが、整数オブジェクトを追加しているため、ランタイムエラーが発生するはずです。しかし、それはあまりにもランタイムエラーを与えることはありませんでした。なぜそうなのか? – emilly

+2

@emilly:実行時にジェネリックが存在しないため。彼らは*消去されます*。したがって、実行時には、すべてのコレクションが未処理(未パラメータ化)のように動作します。 –

+0

新しいArrayList ()を実行する利点はありません。実際に、要素型の右手にCollectionを宣言することは無用な例外です。警告を抑制する警告です。 – emilly

0

最初の例では、コレクションは「未処理」です。これは、通常は警告になりますが、エラーは発生しません(正確なセットアップによって異なります)。これはJava 5より前のすべてのレガシーコードをコンパイルできるようにするために重要です。

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

+0

理想的には実行時エラーが発生するはずですが、それはスローしませんでした:( – emilly

0

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

上:コレクションはジェネリック型なしで宣言できます。これはraw typeと呼ばれます。コレクションは、任意の種類のコレクションを保持できます。生の型指定されたコレクションでは、実行時にの可能性があります。は、コンパイラが通常警告をスローするランタイム例外を引き起こす整数のコレクションとして文字列のコレクションを使用します。上記の例でコレクションをタイプしていないので、コンパイラはこれらの実行時例外を防ぐことができません。それが何であるかを知っていて、何をしているのかを知っているなら、警告は無視することができます。

以下:ただし、コレクションとして宣言された変数<文字列>には、どのような種類のコレクションも保持できません。 で、String型のコレクションでなければなりません。それは強い型付けされています。コンパイラはこれをエラーと見なすのが正しいです。

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

Javaはstrong typedです。これはtype safetyを保証します。上記のスニペットは型安全ではありませんが、それにもかかわらずJavaでは許可されています。おそらくこれは歴史的な理由によるものです。GenericsはJava 1.5でのみ導入されています。したがって、上記のスニペットでコンパイルエラーが発生すると、Java 1.5コンパイラでJava 1.4のほとんどのコードが壊れてしまいます。

すべてのプログラミング言語がそのような下位互換性のある方法(PHPなど)で発展するわけではありません。 Java 1.5を導入するときには、後方互換性が型安全性よりも重視されていたようです。

関連する問題