2011-12-04 10 views
2

ArrayStoreExceptionの内容を理解しています。私の質問です:なぜこれはコンパイラによってキャッチされていないのですか?ArrayStoreExceptionsをJavaコンパイラがキャッチできないのはなぜですか?

これは奇妙な例かもしれませんが、あなたがこれを行うと言う:

HashMap[] h = new LinkedHashMap[4]; 
    h[0] = new PrinterStateReasons(); 

なぜコンパイラはこれが有効でないことを認識できないのですか?

答えて

4

コンパイラに与えた情報があなたの行っていることを許しているからです。無効なランタイム状態のみです。 h変数はHashMap[]と宣言されています。つまり、hまでは、HashMapを実装するものはすべて有効な要素です。 PrinterStateReasonsHashMapを実装しているので、h[0] = new PrinterStateReasons();は完全に有効なステートメントです。同様に、LinkedHashMapHashMapを実装しているため、HashMap[] h = new LinkedHashMap[4];というステートメントは完全に有効なステートメントです。 ランタイムの場合、PrinterStateReasonsオブジェクトをLinkedHashMap配列の要素として格納しようとしますが、これは代入互換ではありません。

あなたが与えた2つのステートメントは連続していますが、一般化された現実ははるかに複雑です。考えてみましょう:

HashMap[] h = foo.getHashMapArray(); 
h[0] = new PrinterStateReasons(); 

// ... elsewhere, in some `Foo` class -- perhaps compiled 
// completely separately from the code above, perhaps 
// even by a completely different team and even a different 
// compiler -- and only combined with the code above at runtime... 

public HashMap[] getHashMapArray() { 
    return new LinkedHashMap[4]; 
} 
+0

コンパイル時に参照がまだLinkedHashMapsの配列を指していないため、実行時にのみ発生すると言っていますか? – varatis

+0

@varatis:**はコンパイル時に**参照はありません。型シグネチャのみ。コンパイラが 'LinkedHashMap'sだけが' h'に格納されるようにするには、 'LinkedHashMap [] h'として宣言する必要があります。 –

+0

LinkedHashMapがまだHashMap配列に格納されていないので、コンパイラはそれをキャッチしません。なぜ私のコードが法的プログラムであるのか理解していますが、コンパイル時にチェックできない理由を正確に理解できません。私が尋ねたことが正しいのかどうか教えてください。編集:また、多分答えはちょうどこれはどのようにコンパイラが書かれていないです。いずれにせよ、私に教えてください。 – varatis

0

コンパイラがキャッチすることはできませんあなたがより一般的な型の配列を使用して、特定の型の配列を参照するときです:

String[] s = new String[10]; 
Object[] o = s; 
o[0] = new Integer(5); 

コンパイラ、それはノーを持っているので、それを検出することはできません変数の宣言から、配列の実際の型を知ることができます。

String []もObject []でも、List<String>List<Object>ではないため、このジェネリックコレクションには問題はありません。配列よりもコレクションを好むもう一つの理由。

+0

ああ、OK。私はこのクラスを知らなかったし、それが標準クラスであるとは思わなかった。 –

0

Java言語仕様によれば、これは有効なプログラムです。エラーとしてフラグを立てたコンパイラは仕様を実装していないため、互換性のあるJavaコンパイラではありません。互換性のないコンパイラの実際の害は、ポータブルではないソースコードを書く人々につながることです。例えばあるコンパイラでコンパイルしますが、別のコンパイラでコンパイルしません

コンパイラが合法的に行うことができる最良のことは、に警告することです。あなたはコードが常に例外をスローすることになります。たとえば、コンパイラでは、常にスローされるnullポインタ例外について警告します。私は、分析がより複雑で、間違いが少なくなるため、配列インデックスのケースではそうしないと思います。

0

まあ、私はスマートコンパイラは静的にその時間を分析することができるだろうと想定してのLinkedHashMap []行で2

しかし、おそらくそれ(潜在的にかなり複雑な分析ではなく、これがない場合よりも何か他のものになることはありませんコンパイラはhに割り当てられているものを本当に知ることができません。 LinkedHashMapではなく、PrinterStateReasonsをHashMapに割り当てることができます。

関連する問題