Основы: углубленный анализ исключений JAVA.

Java
Основы: углубленный анализ исключений JAVA.
  • Когда в методе возникает исключение, создается объект исключения, который передается JVM для обработки.Объект исключения содержит имя исключения, описание исключения и состояние приложения в момент возникновения исключения. Процесс создания объекта исключения и передачи его JVM называется созданием исключения. Это будет серия вызовов методов, упорядоченный список этой серии вызовов методов называется стеком вызовов.
  • JVM просматривает стек вызовов, чтобы увидеть, есть ли код, который может обрабатывать исключения.Когда JVM находит код, который может обрабатывать исключения, он передает возникшее исключение. Если JVM не найдет блок кода, который может обработать исключение, JVM перенаправит исключение обработчику исключений по умолчанию, который распечатает информацию об исключении.

1 Классификация исключений и наследование

  • Throwable — это надкласс всех ошибок и исключений в языке Java. Throwable содержит два подкласса: Error (ошибка) и Exception (исключение)
  • Ошибки не обрабатываются в программе, эти ошибки являются непроверенными исключениями, некодирующими ошибками. Поэтому при возникновении таких ошибок программа не должна обрабатывать такие ошибки. По соглашению мы также не должны реализовывать какие-либо новые подклассы Error.
  • Исключение — это исключение, которое может перехватить и обработать сама программа. Исключение делится на две категории: исключение времени выполнения (RuntimeException) и исключение времени компиляции (проверяемое исключение).

2 Анализ нескольких распространенных классов исключений

  • RuntimeException (непроверяемое исключение) — это надкласс исключений, создаваемых Java во время выполнения виртуальной машины. Любой подкласс RuntimeException, созданный во время выполнения метода, не нужно объявлять в предложении throws, потому что это uncheckedExcepiton. Общие пять видов RuntimeException
    • java.lang.ArithmeticException (арифметическое исключение)
    • java.lang.ClassCastException (исключение преобразования типа)
    • java.lang.IllegalArgumentException (исключение недопустимого параметра)
    • java.lang.IndexOutOfBoundsException (исключение индекса массива за пределами границ)
    • java.lang.NullPointerException (исключение нулевого указателя)
  • Определение проверенного исключения: Исключение в Exception, отличное от RuntimeException и его подклассов. Особенности: Компилятор Java требует, чтобы программа перехватывала или объявляла, что это исключение было выброшено.
    • java.io.IOException (исключение потока ввода-вывода)
    • java.lang.ClassNotFoundException (исключение указанного класса не найдено)
    • java.lang.NoSuchFieldException (указанное поле не найдено, исключение)
    • java.lang.NoSuchMetodException (указанный метод не найден)
    • java.lang.IllegalAccessException (исключение незаконного доступа)
    • java.lang.InterruptedException (прерванное исключение)

3 ключевые слова исключений Java

ключевые слова Описание действия
try{ } Код, который может сгенерировать исключение, помещается в блок try.Когда в блоке try возникает исключение, оно будет сгенерировано.
catch(e) Перехват исключения e; catch используется для перехвата исключений, возникающих в блоках оператора try, можно объявить несколько перехватов, а в перехватчике также можно перехватить несколько исключений.
finally Блок finally всегда выполняется. В основном используется для повторного использования ресурсов (таких как соединения с базой данных, соединения TCP и файловые потоки), открытых в блоках кода попытки.
throw для создания исключений
throws Объявите исключения, которые может генерировать метод
  • Уведомление:Код, наконец, должен быть выполнен до выполнения операторов return и throw в try, catch или где-либо еще. Если в finally есть операторы return и throw, метод завершается после выполнения операторов return или throw в finally.
public int hello(String fileName) throws RuntimeException{
 int a = 10;
    try{
        File file = new File(fileName);
        FileInputStream in = new FileInputStream(file);
        return a; // 返回值10
    }catch (FileNotFoundException e){
        System.out.println("error occurred");
    }catch (ArithmeticException | IndexOutOfBoundsException e){
        System.out.println("whatever");
    } finally{
        System.out.println("finally");
        a = 20; // finally修改a,也不会改变try里 return 10 的结局
        // return a; //如果此处返回,则返回值等于 20
    }
    return -1;
}

4 Примечания по обработке исключений в процессе разработки

  • Создавайте явные исключения и документируйте их
    • Если есть исключение, которое необходимо обрабатывать извне в методе, объявите, что throws выдает конкретное исключение, которое удобно обрабатывать вызывающей стороне.
    • Когда метод объявлен для создания исключения, он также должен быть аннотирован. Цель состоит в том, чтобы предоставить вызывающей стороне как можно больше информации для облегчения обработки исключений.
  • Определение исключений с помощью идентифицирующих сообщений: Легко определить проблему
  • Сначала поймать наиболее конкретное исключение подкласса
    • Если суперкласс исключения перехватывается первым, например, catch (Exception e), код, который перехватывает catch (RunTimeExcption e) позже, не будет выполняться.
  • Не ловить класс Throwable
    • Поскольку Throwable является надклассом Error и Exception, Error представляет собой JVM, ошибку системного уровня, и, как правило, ее не следует захватывать и обрабатывать.
  • Не обрабатывать исключения после перехвата: основная причина ненормальной ошибки не может быть обнаружена.Рекомендуется, по крайней мере, протоколировать выходные данные.
  • Не логировать и не выбрасывать исключения: Вызывает одно и то же исключение для вывода нескольких идентичных журналов, найти источник ошибки непросто.
  • Не отбрасывайте исходное исключение при упаковке нового исключения
    • Если вы отбросите исходное исключение, вы потеряете трассировку стека и сообщение исходного исключения, что затруднит анализ события исключения.
  • Примечание. Исключения могут повлиять на производительность.
    • Затраты производительности на обработку исключений очень высоки, создание исключения происходит очень медленно, а создание исключения занимает 1–5 мс. Старайтесь не использовать исключения для управления логикой вашего кода.

5 исключений и AutoCloseable (синтаксический сахар 1.7-JDK)

  • При перехвате обработки исключений мы часто открываем ресурсы (TCP-соединения, файловые потоки) в попытке. Чтобы предотвратить закрытие ресурса из-за возникновения исключения, закрытие ресурса необходимо выполнить в коде finally.
  • Есть удобный способ? После версии 1.7 JDK java предоставляет синтаксический сахар try--with-resource. Объект ресурса должен реализовывать AutoCloseable. Когда ресурс открывается в try(), связанный ресурс будет автоматически закрыт, и ручное выполнение больше не требуется, является ли это нормальным выходом или ненормальным выходом
  • Все подклассы InputStream наследуют AutoCloseable, пример автоматического закрытия класса ресурсов FileInputStream.
File file = new File("./text.txt");
try (FileInputStream in =new FileInputStream(file)){
    ...//数据操作
} catch (Exception e) {
    log.error(e.getMessage(), e);
    ...
}

6 Разница между броском и броском

  • Ключевое слово throw используется внутри метода и может использоваться только для создания исключения. Оно используется для создания исключений в методе или блоке кода. Могут быть созданы как проверенные, так и непроверенные исключения.
  • Ключевое слово throws используется в объявлениях методов, которые могут генерировать несколько исключений, чтобы указать список исключений, которые может генерировать метод. Метод использует throws для определения списка исключений, которые могут быть выброшены.Метод, вызывающий метод, должен содержать код, который может обрабатывать исключение, в противном случае соответствующее исключение должно быть объявлено с ключевым словом throws в сигнатуре метода.

7 Класс Throwables Guava для понимания

  • Если вам нужно вызвать цепочку операций для исключений, вы можете использовать класс инструментов Throwables, общие методы Throwables:
//以list的方式得到throwable的异常链
public static List<Throwable> getCausalChain(Throwable throwable)
//返回最底层的异常
public static Throwable getRootCause(Throwable throwable)
//把受检查的异常转换为运行时异常
//获取异常调用链的描述输出(每一行都有)
public static String getStackTraceAsString(Throwable throwable)
//如果异常是declaredType类似,则抛出异常,传递throwable
public static <X extends Throwable> void propagateIfInstanceOf(
      @Nullable Throwable throwable, Class<X> declaredType) throws X
//当且仅当它是一个RuntimeException和Error时,或者是一个X的实例时,传递throwable
void propagateIfPossible(Throwable, Class<X extends Throwable>) throws X
//将Throwable转为RuntimeException,不建议使用此方法
public static RuntimeException propagate(Throwable throwable)
  • пример
public static void main(String args[]) throws FileNotFoundException {
    try {
        File file = new File("./text.txt");
        FileInputStream inputStream = new FileInputStream(file);
    } catch (Exception e) {
     //获取异常调用栈信息,并打印(或者保存在其他地方)
        String errorMsg = Throwables.getStackTraceAsString(e);
        System.out.println(errorMsg);
        //如果e是FileNotFoundException,直接抛出
        Throwables.propagateIfInstanceOf(e, FileNotFoundException.class);
        //其他Throwable 转为 RuntimeException类抛出
        throw Throwables.propagate(e);
    }
}

Обратите внимание на паблик аккаунт и общайтесь вместе

Справочная статья