Exception — введение в Java 034 #
Предположим, что пишем программу для кофеавтомата.
При выборе капучино, наш автомат собирает напиток из воды, кофе, молока. Мы же ему написали:
- Возьми одну порцию воды
- Возьми одну порцию кофе
- Возьми порцию молока
- Сделай по рецепту кофе.
Если одного из ингридиентов не будет, то автомат не сможет сделать кофе и возможно зависнет в ожидании ингредиентов или поломается и техник должен будет перезапускать его заново.
Подобные непонятные ситуации возникают при выполнении недопустимых действий, как деление на ноль; при запросе данных, которых больше нет, например сайт, который был указан для отправки сообщений временно или вообще больше не работает.
Ситуации могут быть ожидаемы(всегда при работе с записью на диск, а вдруг у пользователя нет прав?) или из опыта работы прошлых лет (вода в кофейном автомате иногда заканчивается).
Суть в том, что ошибки надо отловить, а программу довести до конца. Ведь если воды в кофейном автомате на вокзале нет, то деньги надо вернуть, отослать сигнал бедствия офис-менеджеру или технику по емайлу и выключить автомат.
Давайте посмотрим на примере.
public static void main(String[] args){
int[] array = new int[5];
int element = array[5];
}
При запуске этого метода мы получим ошибку:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
at TestTryCatch.main(TestTryCatch.java:9)
В ошибке говорится, что у нас ArrayIndexOutOfBoundsException, что логично, ведь на пятом месте в массиве будет шестой элемент, а у нас массив всего из пяти элементов. И нам советуется попробовать трай кэтч TestTryCatch. Давайте попробуем:
public class TestTryCatch {
public static void main(String[] args){
/* int[] array = new int[5];
int element = array[5];*/
testArr();
}
static void testArr(){
// инициализация массива с пятью элементами.
int[] array = new int[5];
try {
int element = array[5];
// это условие никогда не будет выполнено
// потому что у нас в этом месте ошибка
System.out.println("Я НИКОГДА НЕ УВИЖУ ТЕРМИНАЛ");
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println("Мы поймали ошибку");
}
// выполнение оставшейся части программы
System.out.println("Область видимости программы вне блока try catch");
}
}
Прошу заметить, что оператор catch знал какая ошибка может возникнуть и словил именно её - попытку взять несуществующий элемент. Если у нас будет другая ошибка, то мы её не словим. Если мы добавим в блок try строчку int a = 5/0;, то наша программа завершится новым Exception.
Exception in thread "main" java.lang.ArithmeticException: / by zero
at TestTryCatch.testArr(TestTryCatch.java:16)
at TestTryCatch.main(TestTryCatch.java:10)
В такой ситуации мы можем добавить finally
public class TestTryCatch {
public static void main(String[] args) {
/* int[] array = new int[5];
int element = array[5];*/
testArr();
}
static void testArr() {
// инициализация массива с пятью элементами.
int[] array = new int[5];
try {
int a = 5 / 0;
int element = array[5];
// это условие никогда не будет выполнено
// потому что у нас в этом месте ошибка
System.out.println("Я НИКОГДА НЕ УВИЖУ ТЕРМИНАЛ");
} catch (ArrayIndexOutOfBoundsException ex) {
System.out.println("Мы поймали ошибку");
} finally {
System.out.println("Выполнение финального блока: шеф всё плохо, посмотри код");
}
// выполнение оставшейся части программы
System.out.println("Область видимости программы вне блока try catch");
}
}
Домашнее задание #
Есть номера домов в текстовом формате. Используя Integer.parseInt попытаться спарсить различные строки. Возможные ошибки отловить и вывести на экран полезную для оператора информацию.
Подсказка:
String str1 = "123";
int num1 = Integer.parseInt(str);
String str2 = "№123";
int num2 = Integer.parseInt(str2);
Проверьте возможно ли оператор catch использовать несколько раз:
try {
//code
} catch (ExceptionType1 e1) {
// catch block
} catch (ExceptionType1 e2) {
// catch block
} finally {
// finally block always executes
}
Дополнительные материалы #
https://docs.oracle.com/javase/tutorial/essential/exceptions/try.html