Исключение Rethrow в java

у меня очень простой вопрос о повторном исключении в Java.

вот фрагмент кода:

public static void main(String[] args) throws FileNotFoundException {
    try {
        FileReader reader = new FileReader("java.pdf");
    } catch (FileNotFoundException ex) {
        throw ex;
    }
}

public static void main(String[] args) throws FileNotFoundException {        
        FileReader reader = new FileReader("java.pdf");        
}

почему нам нужно повторно бросить ex в первой версии, в то время как вторая версия выглядит более элегантно? Каковы могут быть преимущества и какая версия предпочтительнее другой?

7 ответов


вы правы. Вторая версия лучше. Более того, первая версия не имеет никакого смысла. Он делает то же самое, за исключением того, что трассировка стека исключения будет "неправильной".

существуют следующие причины для исключения "повторного броска":

  1. если у вас есть что-то делать раньше.
  2. если вы ловите исключение одного типа и бросаете исключение другого типа:

пример:

try {
   // do something
} catch (IOException ioe) {
    throw new IllegalStateException(ioe);
}

в приведенном примере повторное бросание Exception не служит никакой цели.

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


Я бы только поймал/перестроил исключение (вместо того, чтобы просто бросать его), если бы я хотел сделать что - то еще в блоке catch-например, написать оператор журнала перед перестроением.


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

try {
    FileReader reader = new FileReader("java.pdf");
} catch (FileNotFoundException ex) {
    throw new ServletException(ex);
}

вопрос в том, почему вы думаете, что вам нужно переосмыслить исключение. Неужели затмение предложило окружение с try-catch? На практике мы редко переосмысливаем одно и то же исключение, но очень часто ловим одно и бросаем другое, что обертывания первый, особенно если исключение оболочки не отмечено. Это происходит всякий раз, когда у вас есть вызовы, объявляющие проверенные исключения, но метод, в котором вы пишете эти вызовы, не объявляет эти исключения:

public int findId(String name) {
  try {
    return db.select("select id from person where name=?", name);
  } catch (SQLException e) {
    throw new RuntimeException(e);
  }
}

поток выполнения останавливается сразу после throw оператор; любые последующие операторы не выполняются. Ближайший вшита try блок проверяется на наличие catch оператор, соответствующий типу исключения.

если он находит совпадение, управление передается в этот оператор. Если нет, то следующий заключительный try оператор проверен и так далее. Если нет соответствия catch нашел, то обработчик исключений по умолчанию останавливает программу и печатает трассировку стека.

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

это можно сделать, включив throws предложение в объявлении метода. А throws предложение перечисляет типы исключений, которые может вызвать метод. Это необходимо для всех исключений, кроме исключений типа Error или RuntimeException, или любой из их подклассы. Все остальные исключения, которые может бросить метод, должны быть объявлены int throws предложения. Если это не так, произойдет ошибка времени компиляции.


обе версии будут выводить один и тот же stacktrace

без try / catch

import java.io.FileNotFoundException;
import java.io.FileReader;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
//        try {
            FileReader reader = new FileReader("java.pdf");
//        } catch (FileNotFoundException ex) {
//            throw ex;
//        }
    }
}

выводит

Exception in thread "main" java.io.FileNotFoundException: java.pdf (The system cannot find the file specified)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at java.io.FileReader.<init>(FileReader.java:58)
    at Test.main(Test.java:7)

С try / catch / throw же исключение

import java.io.FileNotFoundException;
import java.io.FileReader;

public class Test {
    public static void main(String[] args) throws FileNotFoundException {
        try {
            FileReader reader = new FileReader("java.pdf");
        } catch (FileNotFoundException ex) {
            throw ex;
        }
    }
}

будет выводиться точно так же, как и раньше

Exception in thread "main" java.io.FileNotFoundException: java.pdf (The system cannot find the file specified)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at java.io.FileReader.<init>(FileReader.java:58)
    at Test.main(Test.java:7)

try/catch / throw исключение упаковки

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

import java.io.FileNotFoundException;
import java.io.FileReader;

public class Test {
    public static void main(String[] args) {
        try {
            FileReader reader = new FileReader("java.pdf");
        } catch (FileNotFoundException ex) {
            throw new RuntimeException("Error while doing my process", ex);
        }
    }
}

вы можете четко видеть проблему верхнего уровня (мой процесс не завершен) и первопричину, которая привела к этому (java.PDF-файл не найден)

Exception in thread "main" java.lang.RuntimeException: Error while doing my process
    at Test.main(Test.java:9)
Caused by: java.io.FileNotFoundException: java.pdf (The system cannot find the file specified)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(FileInputStream.java:195)
    at java.io.FileInputStream.<init>(FileInputStream.java:138)
    at java.io.FileInputStream.<init>(FileInputStream.java:93)
    at java.io.FileReader.<init>(FileReader.java:58)
    at Test.main(Test.java:7)