ArrayIndexOutOfBoundsException
- исключение времени выполнения (поскольку оно является потомком java.lang.RuntimeException
), поэтому теоретически оно может быть выброшено где угодно. Все исключения во время выполнения могут быть вызваны любым кодом, без необходимости содержать метод, содержащий объявление в предложении throws
; таким образом, компилятор не пытается проверить, что такое исключение может фактически быть сгенерировано любым данным блоком кода. Это было бы невозможно в любом нетривиальном случае в любом случае; любой код, который включает в себя хотя бы один вызов метода для неконечного класса , может вызвать такое исключение (даже если ни один из ваших текущих классов не делает этого, во время выполнения может использоваться другой подкласс).
С другой стороны, IOException
является проверенным исключением, и поэтому может быть выдано только методами, которые явно объявили его в своем throws
предложении *.
См. в этой статье Sun , где немного больше философии относительно проверенных и непроверенных исключений. Знайте также, что это что-то вроде религиозной войны, когда люди настаивают на том, чтобы все исключения были с обеих сторон.
EDIT : Чтобы уточнить, в вашем первом примере компилятор мог , вероятно, проверить, что AIOOBE никогда не будет выброшен. Но это не так; во-первых, потому что это может быть сделано только в таких простых случаях (например, в этом), что это не даст никакой реальной выгоды; во-вторых, потому что, возможно, было бы более запутанным, если бы вам иногда разрешалось включать «невозможные» исключения времени выполнения, а иногда нет, например ::
// Preparation stuff
private void myNoop() {}
public void publicNoop() {}
public final void finalNoop() {}
// hypothetically illegal (same as your first example)
try {
// do nothing
} catch (ArrayIndexOutOfBoundsException e) {}
// hypothetically illegal (myNoop() can't be overridden)
try {
myNoop();
} catch (ArrayIndexOutOfBoundsException e) {}
// hypothetically illegal (finalNoop() can't be overridden)
try {
finalNoop();
} catch (ArrayIndexOutOfBoundsException e) {}
// legal (publicNoop() could do anything at runtime)
try {
publicNoop();
} catch (ArrayIndexOutOfBoundsException e) {}
Мне кажется странным, что изменение уровня доступа или завершенности метода (или фактически класса) внезапно изменит легальность перехвата определенных исключений времени выполнения. Особенно, если учесть, что блок catch может быть на несколько уровней выше в стеке, чем изменяемый метод ...
Кроме того, наличие блока catch, который никогда не будет вызываться, действительно безопасен. «Вот как вы имеете дело с AIOOBE, если таковой возникнет» - и это никогда не происходит во время выполнения. То же самое может произойти и с проверенными исключениями; например, Callable.call()
объявлено для выброса Exception
, но конкретная используемая вами реализация может никогда не выдать никаких исключений - так что, опять же, у вас будут инструкции о том, как обрабатывать исключение, которое будет никогда не вызываться во время выполнения.
В конце дня компилятор просто указывает на несоответствия: «Вы уверены , что вы хотели перехватить IOException, так как этот код никогда не будет запущен?» Это как статическая типизация в том, что она автоматически предупреждает вас об изменениях в интерфейсе. Существуют исключения времени выполнения, поэтому вам не нужно объявлять каждый метод для выдачи NullPointerException
и т. Д.
* Технически это не совсем верно, здесь есть несколько лазеек низкого уровня, но в целом это так. Исключениями являются, как правило, аномалии, артефакты и / или все равно не рекомендуется.