コンパイラに与えた情報があなたの行っていることを許しているからです。無効なランタイム状態のみです。 h
変数はHashMap[]
と宣言されています。つまり、h
までは、HashMap
を実装するものはすべて有効な要素です。 PrinterStateReasons
はHashMap
を実装しているので、h[0] = new PrinterStateReasons();
は完全に有効なステートメントです。同様に、LinkedHashMap
はHashMap
を実装しているため、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];
}
コンパイル時に参照がまだLinkedHashMapsの配列を指していないため、実行時にのみ発生すると言っていますか? – varatis
@varatis:**はコンパイル時に**参照はありません。型シグネチャのみ。コンパイラが 'LinkedHashMap'sだけが' h'に格納されるようにするには、 'LinkedHashMap [] h'として宣言する必要があります。 –
LinkedHashMapがまだHashMap配列に格納されていないので、コンパイラはそれをキャッチしません。なぜ私のコードが法的プログラムであるのか理解していますが、コンパイル時にチェックできない理由を正確に理解できません。私が尋ねたことが正しいのかどうか教えてください。編集:また、多分答えはちょうどこれはどのようにコンパイラが書かれていないです。いずれにせよ、私に教えてください。 – varatis