Почему ArrayStoreExceptions не может быть перехвачен компилятором Java? - PullRequest
2 голосов
/ 05 декабря 2011

Я понимаю, что такое ArrayStoreException.Мой вопрос: почему это не поймано компилятором?

Это может быть странный пример, но, скажем, вы делаете это:

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

Почему компилятор не может распознать, что это неверно?

Ответы [ 4 ]

4 голосов
/ 05 декабря 2011

Потому что информация, которую вы дали компилятору, позволяет вам делать то, что вы делаете. Недопустимо только состояние времени выполнения. Ваша переменная h объявлена ​​как HashMap[], что означает, что для h все, что реализует HashMap, является допустимым элементом. PrinterStateReasons реализует HashMap, и поэтому h[0] = new PrinterStateReasons(); является совершенно допустимым утверждением. Точно так же, поскольку LinkedHashMap реализует HashMap, оператор HashMap[] h = new LinkedHashMap[4]; является совершенно допустимым оператором. Только в время выполнения вы пытаетесь сохранить объект PrinterStateReasons как элемент в массиве LinkedHashMap, что вы не можете сделать, так как он не совместим с назначениями.

Два высказывания, которые вы дали, являются смежными, но, конечно, обобщенная реальность гораздо сложнее. Рассмотрим:

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 голосов
/ 05 декабря 2011

Ну, я полагаю, что умный компилятор сможет статически анализировать, что h никогда не может быть ничем иным, как LinkedHashmap [] в строке 2.

Но без этого (потенциально довольно сложная аналитика, возможно, неэто простой случай, хотя) компилятор не может действительно знать, что назначено h.Вы можете назначить PrinterStateReasons для HashMap, но не для LinkedHashMap.

0 голосов
/ 05 декабря 2011

Спецификация языка Java говорит, что это действительная программа. Компилятор, который пометил его как ошибку, не реализует спецификацию и, следовательно, не является совместимым компилятором Java. Настоящий вред несовместимого компилятора состоит в том, что он приводит к тому, что люди пишут исходный код, который не переносим; например компилируется с одним компилятором, но не с другим.

Лучшее, что может легально сделать компилятор, - это предупредить , что код всегда будет выдавать исключение. Например, некоторые компиляторы будут предупреждать вас об исключениях нулевого указателя, которые всегда будут выбрасываться. Я предполагаю, что они не делают этого в случае индекса массива, потому что анализ более сложен, и ошибка совершается реже.

0 голосов
/ 05 декабря 2011

То, что компилятор не может поймать, это когда вы ссылаетесь на массив определенного типа, используя массив более общего типа:

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

Компилятор не может обнаружить его, потому что он никак не может изобъявление переменной, чтобы знать фактический тип массива.

Обратите внимание, что у вас не будет этой проблемы с универсальными коллекциями, потому что, хотя String [] также является Object [], List<String> неList<Object>.Еще одна причина предпочитать коллекции массивам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...