Часть заголовка метода throws
То обстоятельство, что метод не обрабатывает возникающее в нем исключение, а выбрасывает (throws) его, следует отмечать в заголовке метода служебным словом throws и указанием класса исключения:
private static void f(int n) throws ArithmeticException{ System.out.println(" 10 / n = " + (10 / n)); }
Почему же мы не сделали это в листинге 16.3? Дело в том, что спецификация JLS делит все исключения на проверяемые (checked), те, которые проверяет компилятор, и непроверяемые (unchecked). При проверке компилятор замечает необработанные в методах и конструкторах исключения и считает ошибкой отсутствие в заголовке таких методов и конструкторов пометки throws. Именно для предотвращения подобных ошибок мы в предыдущих главах вставляли в листинги блоки обработки исключений.
Так вот, исключения класса RuntimeException и его подклассов, одним из которых является ArithmeticException, непроверяемые, для них пометка throws необязательна. Еще одно большое семейство непроверяемых исключений составляет класс Error и его расширения.
Почему компилятор не проверяет эти типы исключений? Причина в том, что исключения класса RuntimeException свидетельствуют об ошибках в программе, и единственно разумный метод их обработки – исправить исходный текст программы и перекомпилировать ее. Что касается класса Error, то эти исключения очень трудно локализовать и на стадии компиляции невозможно определить место их появления.
Напротив, возникновение проверяемого исключения показывает, что программа недостаточно продумана, не все возможные ситуации описаны. Такая программа должна быть доработана, о чем и напоминает компилятор.
Если метод или конструктор выбрасывает несколько исключений, то их надо перечислить через запятую после слова throws. Заголовок метода main () листинга 16.1, если бы исключения, которые он выбрасывает, не были бы объектами подклассов класса RuntimeException, следовало бы написать так:
public static void main(String[] args) throws ArithmeticException, ArrayIndexOutOfBoundsException{ // Содержимое метода }
Перенесем теперь обработку деления на нуль в метод f () и добавим трассировочную печать, как это сделано в листинге 16.4. Результат – на рис. 16.3.