Операторы try можно вкладывать друг в друга аналогично тому, как можно создавать вложенные области видимости переменных. Если у оператора try низкого уровня нет раздела catch, соответствующего возбужденному исключению, стек будет развернут на одну ступень выше, и в поисках подходящего обработчика будут прове-рены разделы catch внешнего оператора try. Вот пример, в котором два оператора try вложены друг в друга посредством вызова метода.
class MultiNest {
static void procedure() {
try {
int c[] = { 1 };
c[42] = 99;
}
catch(ArrayIndexOutOfBoundsException e) {
System.out.println("array index oob: " + e);
}
}
public static void main(String args[]) {
try {
int a = args.length();
System.out.println("a = " + a);
int b = 42 / a;
procedure();
}
catch (ArithmeticException e) {
System.out.println("div by 0: " + e);
}
}
}
Throw
Оператор throw используется для возбуждения исключения <вруч-ную>. Для того, чтобы сделать это, нужно иметь объект подкласса клас-са Throwable, который можно либо получить как параметр оператора catch, либо создать с помощью оператора new. Ниже приведена общая форма оператора throw.
throw ОбъектТипаThrowable;
При достижении этого оператора нормальное выполнение кода немед-ленно прекращается, так что следующий за ним оператор не выполня-ется. Ближайший окружающий блок try проверяется на наличие соот-ветствующего возбужденному исключению обработчика catch. Если такой отыщется, управление передается ему. Если нет, проверяется следующий из вложенных операторов try, и так до тех пор пока либо не будет най-ден подходящий раздел catch, либо обработчик исключений исполняю-щей системы Java не остановит программу, выведя при этом состояние стека вызовов. Ниже приведен пример, в котором сначала создается объект-исключение, затем оператор throw возбуждает исключительную ситуацию, после чего то же исключение возбуждается повторно - на этот раз уже кодом перехватившего его в первый раз раздела catch.
class ThrowDemo {
static void demoproc() {
try {
throw new NullPointerException("demo");
}
catch (NullPointerException e) {
System.out.println("caught inside demoproc");
throw e;
}
}
public static void main(String args[]) {
try {
demoproc();
}
catch(NulPointerException e) {
System.out.println("recaught: " + e);
}
}
}
В этом примере обработка исключения проводится в два приема. Метод main создает контекст для исключения и вызывает demoproc. Метод demoproc также устанавливает контекст для обработки исключе-ния, создает новый объект класса NullPointerException и с помощью опе-ратора throw возбуждает это исключение. Исключение перехватывается в следующей строке внутри метода demoproc, причем объект-исключение доступен коду обработчика через параметр e. Код обработчика выводит сообщение о том, что возбуждено исключение, а затем снова возбуждает его с помощью оператора throw, в результате чего оно передается обра-ботчику исключений в методе main. Ниже приведен результат, получен-ный при запуске этого примера.
С:\> java ThrowDemo
caught inside demoproc
recaught: java.lang.NullPointerException: demo
Throws
Если метод способен возбуждать исключения, которые он сам не об-рабатывает, он должен объявить о таком поведении, чтобы вызывающие методы могли защитить себя от этих исключений. Для задания списка исключений, которые могут возбуждаться методом, используется ключе-вое слово throws. Если метод в явном виде (т.е. с помощью оператора throw) возбуждает исключе-ние соответствующего класса, тип класса исключений должен быть ука-зан в операторе throws в объявлении этого метода. С учетом этого наш прежний синтаксис определения метода должен быть расширен следую-щим образом:
тип имя_метода(список аргументов) throws список_исключений {}
Ниже приведен пример программы, в которой метод procedure пыта-ется возбудить исключение, не обеспечивая ни программного кода для его перехвата, ни объявления этого исключения в заголовке метода. Такой программный код не будет оттранслирован.
class ThrowsDemo1 {
static void procedure() {
System.out.println("inside procedure");
throw new IllegalAccessException("demo");
}
public static void main(String args[]) {
procedure();
}
}
Для того, чтобы мы смогли оттранслировать этот пример, нам при-дется сообщить транслятору, что procedure может возбуждать исключе-ния типа IllegalAccessException и в методе main добавить код для обработки этого типа исключений :