Исключение — это нештатная ситуация, ошибка во время выполнения программы. Самый простой пример — деление на ноль. Можно вручную отслеживать возникновение подобных ошибок, а можно воспользоваться специальным механизмом исключений, который упрощает создание больших надёжных программ, уменьшает объём необходимого кода и повышает уверенность в том, что в приложении не будет необработанной ошибки.
В методе, в котором происходит ошибка, создаётся и передаётся специальный объект. Метод может либо обработать исключение самостоятельно, либо пропустить его. В любом случае исключение ловится и обрабатывается. Исключение может появиться благодаря самой системе, либо вы сами можете создать его вручную.
Системные исключения возникают при неправильном использовании языка Java или запрещённых приёмов доступа к системе. Ваши собственные исключения обрабатывают специфические ошибки вашей программы.
Вернёмся к примеру с делением. Деление на нуль может предотвратить проверкой соответствующего условия. Но что делать, если знаменатель оказался нулём? Возможно, в контексте вашей задачи известно, как следует поступить в такой ситуации. Но, если нулевой знаменатель возник неожиданно, деление в принципе невозможно, и тогда необходимо возбудить исключение, а не продолжать исполнение программы.
Ошибка 1603: Обновление Java не завершено
Существует пять ключевых слов, используемых в исключениях: try, catch, throw, throws, finally. Порядок обработки исключений следующий.
Операторы программы, которые вы хотите отслеживать, помещаются в блок try. Если исключение произошло, то оно создаётся и передаётся дальше. Ваш код может перехватить исключение при помощи блока catch и обработать его. Системные исключения автоматически передаются самой системой. Чтобы передать исключение вручную, используется throw.
Любое исключение, созданное и передаваемое внутри метода, должно быть указано в его интерфейсе ключевым словом throws. Любой код, который следует выполнить обязательно после завершения блока try, помещается в блок finally
Схематически код выглядит так:
try < // блок кода, где отслеживаются ошибки >catch (тип_исключения_1 exceptionObject) < // обрабатываем ошибку >catch (тип_исключения_2 exceptionObject) < // обрабатываем ошибку >finally < // код, который нужно выполнить после завершения блока try >
Существует специальный класс для исключений Trowable. В него входят два класса Exception и Error.
Класс Exception используется для обработки исключений вашей программой. Вы можете наследоваться от него для создания собственных типов исключений. Для распространённых ошибок уже существует класс RuntimeException, который может обрабатывать деление на ноль или определять ошибочную индексацию массива.
Класс Error служит для обработки ошибок в самом языке Java и на практике вам не придётся иметь с ним дело.
Прежде чем научиться обрабатывать исключения, нам (как и нормальному любопытному коту) хочется посмотреть, а что происходит, если ошибку не обработать. Давайте разделим число котов в вашей квартире на ноль, хотя мы и знаем, что котов на ноль делить нельзя!
Ошибка при подключении к NCALayer. Убедитесь что программа NCALayer запущена — РЕШЕНИЕ В 2021 ГОДУ!
int catNumber; int zero; catNumber = 1; // у меня один кот zero = 0; // ноль, он и в Африке ноль int result = catNumber / zero;
Я поместил код в обработчик щелчка кнопки. Когда система времени выполнения Java обнаруживает попытку деления на ноль, она создаёт объект исключения и передаёт его. Да вот незадача, никто не перехватывает его, хотя это должны были сделать вы. Видя вашу бездеятельность, объект перехватывает стандартный системный обработчик Java, который отличается вредных характером. Он останавливает вашу программу и выводит сообщение об ошибке, которое можно увидеть в журнале LogCat:
Caused by: java.lang.ArithmeticException: divide by zero at ru.alexanderklimov.test.MainActivity.onClick(MainActivity.java:79)
Как видно, созданный объект исключения принадлежит к классу ArithmeticException, далее системный обработчик любезно вывел краткое описание ошибки и место возникновения.
Вряд ли пользователи вашей программы будут довольны, если вы так и оставите обработку ошибки системе. Если программа будет завершаться с такой ошибкой, то скорее всего вашу программу просто удалят. Посмотрим, как мы можем исправить ситуацию.
Поместим проблемный код в блок try, а в блоке catch обработаем исключение.
int catNumber; int zero; try < // мониторим код catNumber = 1; // у меня один кот zero = 0; // ноль, он и в Африке ноль int result = catNumber / zero; Toast.makeText(this, «Не увидите это сообщение!», Toast.LENGTH_LONG).show(); >catch (ArithmeticException e) < Toast.makeText(this, «Нельзя котов делить на ноль!», Toast.LENGTH_LONG).show(); >Toast.makeText(this, «Жизнь продолжается», Toast.LENGTH_LONG).show();
Теперь программа аварийно не закрывается, так как мы обрабатываем ситуацию с делением на ноль.
В данном случае мы уже знали, к какому классу принадлежит получаемая ошибка, поэтому в блоке catch сразу указали конкретный тип. Обратите внимание, что последний оператор в блоке try не срабатывает, так как ошибка происходит раньше строчкой выше. Далее выполнение передаётся в блок catch, далее выполняются следующие операторы в обычном порядке.
Операторы try и catch работают совместно в паре. Хотя возможны ситуации, когда catch может обрабатывать несколько вложенных операторов try.
Если вы хотите увидеть описание ошибки, то параметр e и поможет увидеть его.
catch (ArithmeticException e)
По умолчанию, класс Trowable, к которому относится ArithmeticException возвращает строку, содержащую описание исключения. Но вы можете и явно указать метод e.toString.
НЕСКОЛЬКО ИСКЛЮЧЕНИЙ.
Фрагмент кода может содержать несколько проблемных мест. Например, кроме деления на ноль, возможна ошибка индексации массива. В таком случае вам нужно создать два или более операторов catch для каждого типа исключения. Причём они проверяются по порядку. Если исключение будет обнаружено у первого блока обработки, то он будет выполнен, а остальные проверки пропускаются и выполнение программы продолжается с места, который следует за блоком try/catch.
int catNumber; int zero; try < // мониторим код catNumber = 1; // у меня один кот zero = 1; // ноль, он и в Африке ноль int result = catNumber / zero; // Создадим массив из трёх котов String[] catNames = ; catNames[3] = «Рыжик»; Toast.makeText(this, «Не увидите это сообщение!», Toast.LENGTH_LONG).show(); > catch (ArithmeticException e) < Toast.makeText(this, e.toString() + «: Нельзя котов делить на ноль!», Toast.LENGTH_LONG).show(); >catch (ArrayIndexOutOfBoundsException e) < Toast.makeText(this, «Ошибка: » + e.toString(), Toast.LENGTH_LONG).show(); >Toast.makeText(this, «Жизнь продолжается», Toast.LENGTH_LONG).show();
В примере мы добавили массив с тремя элементами, но обращаемся к четвёртому элементу, так как забыли, что отсчёт у массива начинается с нуля.
Если оставить значение переменной zero равным нулю, то сработает обработка первого исключения деления на ноль, и мы даже не узнаем о существовании второй ошибки. Но допустим, что в результате каких-то вычислений значение переменной стало равно единице. Тогда наше исключение ArithmeticException не сработает. Но сработает новое добавленное исключение ArrayIndexOutOfBoundsException. А дальше всё пойдёт как раньше.
Тут всегда нужно помнить одну особенность. При использовании множественных операторов catch обработчики подклассов исключений должные находиться выше, чем обработчики их суперклассов. Иначе, суперкласс будет перехватывать все исключения, имея большую область перехвата. Иными словами, Exception не должен находиться выше ArithmeticException и ArrayIndexOutOfBoundsException.
К счастью, среда разработки сама замечает непорядок и предупреждает вас, что такой порядок не годится. Увидев такую ошибку, попробуйте перенести блок обработки исключений ниже.
ВЛОЖЕННЫЕ ОПЕРАТОРЫ TRY.
Операторы try могут быть вложенными. Если вложенный оператор try не имеет своего обработчика catch для определения исключения, то идёт поиск обработчика catch у внешнего блока try и т.д. Если подходящий catch не будет найден, то исключение обработает сама система (что никуда не годится).
ОПЕРАТОР THROW.
throw экземпляр_Throwable
Вам нужно создать экземпляр класса Throwable или его наследников. Получить объект класса Throwable можно в операторе catch или стандартным способом через оператор new.
Поток выполнения останавливается непосредственно после оператора throw и другие операторы не выполняются. При этом ищется ближайший блок try/catch соответствующего исключению типа.
try < throw new NullPointerException(«Кота не существует»); >catch (NullPointerException e)
Полное руководство по обработке исключений в Java
Исключение — ошибка, которая нарушает нормальную работу программы. Java обеспечивает надежный объектно-ориентированный способ обработки исключений. Именно его мы и будем изучать в этом руководстве.
Обработка исключений в Java. Краткий обзор
Исключение может возникнуть в разного рода ситуациях: неправильные входные данные, аппаратный сбой, сбоя сетевого соединения, ошибка при работе с базой данных и т.д. Именно поэтому любой Java программист должен уметь правильно обрабатывать исключения, понимать причины их появления и следовать лучшим практикам работы с исключениями даже в небольших проектах.
Java — объектно-ориентированный язык программирования, поэтому всякий раз, когда происходит ошибка при выполнении инструкции, создается объект-исключение, а затем нормальный ход выполнения программы останавливается и JRE пытается найти кого-то, кто может справиться (обработать) это исключение. Объект-исключение содержит много информации об отладке, а именно номер строки, где произошло исключение, тип исключения и т.д.
Что и как происходит, когда появляется ошибка
Когда в методе происходит исключение, то процесс создания объекта-исключения и передачи его в Runtime Environment называется «бросать исключение».
После создания исключения, Java Runtime Environment пытается найти обработчик исключения.
Обработчик исключения — блок кода, который может обрабатывать объект-исключение.
Логика нахождения обработчика исключений проста — прежде всего начинается поиск в методе, где возникла ошибка, если соответствующий обработчик не найден, то происходит переход к тому методу, который вызывает этот метод и так далее.
Пример
У нас есть 3 метода, каждый из которых вызывает друг-друга: А -> В -> С (А вызывает В, а В вызывает С). Если исключение появляется в методе C, то поиск соответствующего обработчика будет происходить в обратном порядке: С -> В -> А (сначала там, где было исключение — в С, если там нет обработчика, то идем в метод В — если тут тоже нет, то идем в А).
Если соответствующий обработчик исключений будет найден, то объект-исключение передаётся обработчику.
Обработать исключение — значит «поймать исключение».
Если обработчик исключений не был найден, то программа завершает работу и печатает информации об исключении.
Обратите внимание, что обработка исключений в Java — это фреймворк, который используется только для обработки ошибок времени выполнения. Ошибки компиляции не обрабатываются рамках обработки исключений.
Основные элементы обработки исключений в Java
Java как завершить программу с ошибкой
Нередко в процессе выполнения программы могут возникать ошибки, при том необязательно по вине разработчика. Некоторые из них трудно предусмотреть или предвидеть, а иногда и вовсе невозможно. Так, например, может неожиданно оборваться сетевое подключение при передаче файла. Подобные ситуации называются исключениями .
В языке Java предусмотрены специальные средства для обработки подобных ситуаций. Одним из таких средств является конструкция try. catch. finally . При возникновении исключения в блоке try управление переходит в блок catch, который может обработать данное исключение. Если такого блока не найдено, то пользователю отображается сообщение о необработанном исключении, а дальнейшее выполнение программы останавливается. И чтобы подобной остановки не произошло, и надо использовать блок try..catch. Например:
int[] numbers = new int[3]; numbers[4]=45; System.out.println(numbers[4]);
Так как у нас массив numbers может содержать только 3 элемента, то при выполнении инструкции numbers[4]=45 консоль отобразит исключение, и выполнение программы будет завершено. Теперь попробуем обработать это исключение:
try < int[] numbers = new int[3]; numbers[4]=45; System.out.println(numbers[4]); >catch(Exception ex) < ex.printStackTrace(); >System.out.println(«Программа завершена»);
При использовании блока try. catch вначале выполняются все инструкции между операторами try и catch. Если в блоке try вдруг возникает исключение, то обычный порядок выполнения останавливается и переходит к инструкции сatch. Поэтому когда выполнение программы дойдет до строки numbers[4]=45; , программа остановится и перейдет к блоку catch
Выражение catch имеет следующий синтаксис: catch (тип_исключения имя_переменной) . В данном случае объявляется переменная ex , которая имеет тип Exception . Но если возникшее исключение не является исключением типа, указанного в инструкции сatch, то оно не обрабатывается, а программа просто зависает или выбрасывает сообщение об ошибке.
Но так как тип Exception является базовым классом для всех исключений, то выражение catch (Exception ex) будет обрабатывать практически все исключения. Обработка же исключения в данном случае сводится к выводу на консоль стека трассировки ошибки с помощью метода printStackTrace() , определенного в классе Exception.
После завершения выполнения блока catch программа продолжает свою работу, выполняя все остальные инструкции после блока catch.
Конструкция try..catch также может иметь блок finally . Однако этот блок необязательный, и его можно при обработке исключений опускать. Блок finally выполняется в любом случае, возникло ли исключение в блоке try или нет:
try < int[] numbers = new int[3]; numbers[4]=45; System.out.println(numbers[4]); >catch(Exception ex) < ex.printStackTrace(); >finally < System.out.println(«Блок finally»); >System.out.println(«Программа завершена»);
Обработка нескольких исключений
В Java имеется множество различных типов исключений, и мы можем разграничить их обработку, включив дополнительные блоки catch:
int[] numbers = new int[3]; try < numbers[6]=45; numbers[6]=Integer.parseInt(«gfd»); >catch(ArrayIndexOutOfBoundsException ex) < System.out.println(«Выход за пределы массива»); >catch(NumberFormatException ex)
Если у нас возникает исключение определенного типа, то оно переходит к соответствующему блоку catch.
Оператор throw
Чтобы сообщить о выполнении исключительных ситуаций в программе, можно использовать оператор throw . То есть с помощью этого оператора мы сами можем создать исключение и вызвать его в процессе выполнения. Например, в нашей программе происходит ввод числа, и мы хотим, чтобы, если число больше 30, то возникало исключение:
package firstapp; import java.util.Scanner; public class FirstApp < public static void main(String[] args) < try< Scanner in = new Scanner(System.in); int x = in.nextInt(); if(x>=30) < throw new Exception(«Число х должно быть меньше 30»); >> catch(Exception ex) < System.out.println(ex.getMessage()); >System.out.println(«Программа завершена»); > >
Здесь для создания объекта исключения используется конструктор класса Exception, в который передается сообщение об исключении. И если число х окажется больше 29, то будет выброшено исключение и управление перейдет к блоку catch.
В блоке catch мы можем получить сообщение об исключении с помощью метода getMessage() .
Источник: metanit.com