Виртуальная Машина Java (в дальнейшем JVM) обрабатывая код, запускает методы один за другим, начиная с метода
main. Когда она доходит до очередного метода, говорится, что этот метод находится на вершине стека. После полного выполнения метода, он удаляется из стека, и сменяется следующим в очереди. Для демонстрации принципа, наберите данный код:
package errorhandling;
public class errorChecking {
public static void main(String[] args) {
System.out.println("Метод Main успешно запущен");
m1();
System.out.println("Метод Main заканчивает свою работу");
}
static void m1() {
System.out.println("Первый метод передаёт привет!(m1)");
m2();
}
static void m2() {
System.out.println("Второй метод передаёт привет(m2)");
}
}
У нас три метода: метод main, метод m1 и метод m2. Когда программа стартует, на вершине стека расположен метод main. Внутри метода main, вызывается метод m1. Вызываясь, он прыгает на верхушку стека. Метод m1 в свою очередь вызывает метод m2. Теперь уже метод m2, прыгает на верхушку стека, временно отстраняя m1. На секунду представьте это — main, сверху m1 и на вершине m2! Сделав свои дела, m2 завершается, и контроль возвращается обратно к m1. Метод m1, завершаясь, тоже удаляется из стека, и управление вновь получает метод main.
Запустите вашу программу и посмотрите на окно вывода:
Метод Main успешно запущен
Первый метод передаёт привет!(m1)
Второй метод передаёт привет(m2)
Метод Main заканчивает свою работу
Если что-то пойдёт не так в методе m2, JVM (Виртуальная Машина Джава, вы помните, да?) будет искать обработчиков ошибок, например блок try … catch. Если в методе m1 обработчика ошибок нет, то исключение будет передано методу m1, в надежде, что он сумеет её обработать. Если и здесь не обнаружит обработчика ошибок,то исключение снова перейдёт по стеку вверх, на этот раз в метод main. Если метод main не взаимодействует с исключением, вы получите странное сообщение об ошибке, напечатанное в окне вывода. В качестве примера, приведите ваш метод m2 к следующему виду:
static void m2() {
int x = 10;
int y = 0;
double z = x / y;
System.out.println( z );
System.out.println("Method Two - m2");
}
Этот метод содержит ошибку деления на ноль.
А вот полный вариант программы, сверьтесь со своим:
package errorhandling;
public class errorChecking {
public static void main(String[] args) {
System.out.println("Метод Main успешно запущен");
m1();
System.out.println("Метод Main заканчивает свою работу");
}
static void m1() {
System.out.println("Первый метод передаёт привет!(m1)");
m2();
}
static void m2() {
int x = 10;
int y = 0;
double z = x / y;
System.out.println( z );
System.out.println("Method Two - m2");
}
}
Запустите программу и посмотрите, что выдаст вам окно вывода:
Метод Main успешно запущен
Первый метод передаёт привет!(m1)
Exception in thread "main" java.lang.ArithmeticException: / by zero
at errorhandling.errorChecking.m2(<u>errorChecking.java:17</u>)
at errorhandling.errorChecking.m1(<u>Solution.java:11</u>)
at errorhandling.errorChecking.main(<u>>Solution.java:5</u>)
Process finished with exit code 1
Вы смотрите на нечто, называемое стек-трейс. Три строки, подчёркнутые голубым, ссылаются на ваши методы, и могут быть найдены в:
имя_пакета.имя_класса.имя_метода
Первая сверху строка — это место, где ошибка возникла — в методе m2. Java проследила, что бы она была обработана ArithmeticException, которая вылавливает ошибки деления на ноль. В методах m2, m1 и main нет обработчика ошибок. Так что программа обработала её обработчиком ошибок по-умолчанию.
Измените ваш метод m1 на следующий:
try {
System.out.println("Первый метод передаёт привет!(m1)");
m2( );
}
catch (ArithmeticException err) {
System.out.println(err.getMessage());
}
Теперь мы обернули метод m2 в блок try. В части catch, мы используем тип исключения, что был выявлен в стек-трейсе — ArithmeticException.
Запустите код снова, и в окне вывода увидите следующее:
Метод Main успешно запущен
Первый метод передаёт привет!(m1)
/ by zero
Метод Main заканчивает свою работу
Заметьте, что сообщение об ошибке вывелось как: "/ by zero". Метод m2 не был выполнен полностью, а был остановлен, когда возникла ошибка. Затем контроль был передан обратно m1. Это произошло благодаря тому, что блок catch сам распознавал ошибку, JVM не стала обращаться к стандартному обработчику ошибок, а вывела сообщение находящееся между фигурными скобками блока catch.
Обратите внимание, что сама программа не была остановлена. Контроль, как обычно перешёл к методу main, откуда m1 был вызван. И последняя строка метода main, таки смогла вывести на экран "End Main method". Это имеет очень-очень важное значение. Если бы вам нужно было значение из m1, для последующей работы где-то в main. И если значения там не окажется, то ваша программа может отработать совсем не так, как вы ожидаете.
Когда вы увидите стек-трейс в окне вывода, просто знайте, что первая строка — это то место, где проблема возникла, а остальные строки (если конечно они есть), куда исключение было передано вверх по стеку, обычно заканчивая методом main.
Перевод с сайта homeandlearn.co.uk
Говорим спасибо: Серегею Сысоеву, Treefeed...
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ