вторник, 8 сентября 2020 г.

Управление исключениями (возникающими ошибками) в Java

  Исключение в программировании - это возникновение ошибок и непредвиденных ситуаций при выполнении программы.

  Исключения (ошибки при выполнении программы) могут возникать в результате:

   - неправильных действий пользователя

   - отсутствии необходимого ресурса на диске

   - потери соединения с сервером по сети

   - ошибки программирования

   - неправильное использование API.

 

   Настраивают управление исключениями для того, чтобы программа чётко знала, как поступать в ситуации появления ошибок при выполнении программы.

   (чтобы предупредить и решить исключительные ситуации в программе, для того чтобы её выполнение могло быть продолжено)

   В частности, механизм исключений позволяет защитить написанный код (программный интерфейс) от неправильного использования пользователем за счет валидации (проверки) входящих данных. 

  Использование исключений в Java позволяет повысить отказоустойчивость программы за счет использования «запасных» путей, отделить логику основного кода от кода обработки исключительных ситуаций за счет использования блоков catch, а также дает возможность переложить обработку исключений на пользователя нашего кода с помощью throws.

 

   Обработка исключений в Java основана на использовании в программе следующих ключевых слов

 

try, catch, finally, throws

 

   1) try – определяет (заключает под собой) блок кода, в котором может произойти исключение;

   2) catch – определяет (заключает под собой) блок кода, в котором происходит обработка исключения;

   (Действия при сбое, который может случиться внутри оператора try)

   3) finally – определяет (заключает под собой) блок кода, который является необязательным, но при его наличии выполняется в любом случае независимо от результатов выполнения блока try.

(Блок finally часто используется для того, чтобы закрыть открытые в блоке try потоки или освободить ресурсы. Однако при написании программы не всегда возможно уследить за закрытием всех ресурсов. Для облегчения этой задачи существует конструкция try-with-resources, которая автоматически закрывает ресурсы, открытые в блоке try).

   Эти ключевые слова используются для создания в программном коде специальных обрабатывающих конструкций: try{}catch, try{}catch{}finally, try{}finally{}.

   На стадии разработки программы мы «ограждаем» опасные участки кода в отношении исключений с помощью блока try{}, предусматриваем «запасные» пути с помощью блока catch{}, в блоке finally{} мы пишем код, который выполняется в программе при любом исходе.

 

   При появлении исключения в блоке try обработчик исключения ищется в следующем за ним блоке catch. Если в catch есть обработчик данного типа исключения – управление переходит к нему. Если нет, то JVM ищет обработчик этого типа исключения в цепочке вызовов методов до тех пор, пока не будет найден подходящий catch. После выполнения блока catch управление передается в необязательный блок finally. В случае, если подходящий блок catch не найден, JVM останавливает выполнение программы, и выводит стек вызовов методов – stack trace, выполнив перед этим код блока finally при его наличии.

   Переменные, определенные в try не могут быть использованы в catch или finally, этот код не скомпилируется. Причина в том, что неизвестно, где именно в блоке try могло быть вызвано исключение, например, возможно, что исключение было вызвано до того, как был объявлен объект.


  4) throw – используется для возбуждения исключения

  5) throws – Это ключевое слово в сигнатуре метода означает, что при определенных условиях метод, может выбросить исключение

    (Ключевое слово throws используется когда не планируется обрабатывать исключение в своем методе, но необходимо предупредить пользователей метода о возможных исключительных ситуациях)

   Такое предупреждение является частью интерфейса метода и предоставляет право пользователю на собственный вариант реализации обработчика исключения (предоставляя написание кода по обработке исключения в Java пользователю метода.).

   После throws указывается тип выбрасываемого исключения.

 

   Типы выбрасываемых исключений:

   Обычно это наследники класса Exception Java.

   Поскольку Java является объектно-ориентированным языком, все исключения в Java представляют собой объекты.

   При возникновении ошибки в процессе выполнения программы исполняющая среда JVM создает объект нужного типа из иерархии исключений Java.

   Иерархия исключений java:




   Throwable - название класса "предка", от которого унаследовано множество возможных исключительных ситуаций.

   Далее всё это множество исключительных ситуаций можно разделить на две группы:

   1) Непроверяемые на стадии компиляции (неконтролируемые) (unchecked)

   Это Error (исключения, унаследованные из класса Error) + RuntimeException (часть исключений - наследников класса Exception)

  RuntimeException – исключения, генерируемые JVM во время выполнения программы. Часто причиной возникновения их являются ошибки программирования.

   К этой группе относятся ситуации, при которых восстановление дальнейшей нормальной работы программы невозможно.

   Это ошибки, возникающие при выполнении программы в результате сбоя работы JVM, переполнения памяти или сбоя системы. Обычно они свидетельствуют о серьезных проблемах, устранить которые программными средствами невозможно, такими как деление на 0, нулевой указатель и т.п.  

 

Список непроверяемых исключений:

   ArithmeticException - арифметическая ошибка, например, деление на ноль

   ArrayIndexOutOfBoundsException - выход индекса за границу массива

   ArrayStoreException - присваивание элементу массива объекта несовместимого типа

   ClassCastException - неверное приведение

   EnumConstantNotPresentException - попытка использования неопределённого значения перечисления

   IllegalArgumentException - неверный аргумент при вызове метода

   IllegalMonitorStateException - неверная операция мониторинга

   IllegalStateException - некорректное состояние приложения

   IllegalThreadStateException - запрашиваемая операция несовместима с текущим потоком

   IndexOutofBoundsException - тип индекса вышел за допустимые пределы

   NegativeArraySizeException - создан массив отрицательного размера

   NullPointerException - неверное использование пустой ссылки

NullPointerException (оно же NPE)  - это исключение, которое выбрасывается каждый раз, когда вы обращаетесь к методу или полю объекта по ссылке, которая равна null.

   NumberFormatException - неверное преобразование строки в числовой формат SecurityException - попытка нарушения безопасности

   StringIndexOutOfBounds - попытка использования индекса за пределами строки

   TypeNotPresentException - тип не найден

   UnsupportedOperationException - обнаружена неподдерживаемая операция

 

 

   2) Проверяемые на стадии компиляции (предвидимые еще на стадии написания программы) (контролируемые) (checked)

   Это Exception (кроме RuntimeException)

   Основная часть работы разработчика на Java при работе с исключениями – обработка таких ситуаций: проверяемые исключения должны быть явно пойманы в теле метода или объявлены в секции throws метода.

   Для проверяемых исключений ожидается, что другие разработчики, использующие API, будут знать, как обращаться с исключениями.


   Список проверяемых системных исключений, которые можно включать в список throws:

   ClassNotFoundException - класс не найден

   CloneNotSupportedException - попытка клонировать объект, который не реализует интерфейс Cloneable

   IllegalAccessException - запрещен доступ к классу

   InstantiationException - попытка создать объект абстрактного класса или интерфейса

   InterruptedException - поток прерван другим потоком

   NoSuchFieldException - запрашиваемое поле не существует

   NoSuchMethodException - запрашиваемый метод не существует

   ReflectiveOperationException - исключение, связанное с рефлексией

 

   Пример использования ключевых слов в java-программе:

//метод считывает строку с клавиатуры

public String input() throws MyException {//предупреждаем с помощью throws,
// что метод может выбросить исключение MyException
      BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    String s = null;
//в блок try заключаем код, в котором может произойти исключение, в данном
// случае компилятор нам подсказывает, что метод readLine() класса
// BufferedReader может выбросить исключение ввода/вывода
    try {
        s = reader.readLine();
// в блок  catch заключаем код по обработке исключения IOException
    } catch (IOException e) {
        System.out.println(e.getMessage());
// в блоке finally закрываем поток чтения
    } finally {
// при закрытии потока тоже возможно исключение, например, если он не был открыт, поэтому “оборачиваем” код в блок try
        try {
            reader.close();
// пишем обработку исключения при закрытии потока чтения
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }
    }

    if (s.equals("")) {
// мы решили, что пустая строка может нарушить в дальнейшем работу нашей программы, например, на результате этого метода нам надо вызывать метод substring(1,2), поэтому мы вынуждены прервать выполнение программы с генерацией своего типа исключения MyException с помощью throw
        throw new MyException("String can not be empty!");
    }
    return s;
}
 

 Этот же пример с помощью try-with-resources:

public String input() throws MyException {
    String s = null;
    try(BufferedReader reader = new BufferedReader(new InputStreamReader(System.in))){
        s = reader.readLine();
   } catch (IOException e) {
       System.out.println(e.getMessage());
   }
    if (s.equals("")){
        throw new MyException ("String can not be empty!");
    }
    return s;
}

Комментариев нет:

Отправить комментарий

Наследование в Java

   «родительское/дочернее»     Наследование (inheritance) - свойство системы, позволяющее описать (создать) новый класс на основе уже су...