Зачем использовать IOexception вместо исключения при ловле?

Я не могу правильно сформулировать это для поисковой системы, чтобы получить какие-либо значимые результаты.

try{
    BufferedReader reader = new BufferedReader( new FileReader("foo.bar") );
}
catch(Exception e){
    println( e.getMessage() );
}

так FileReader бросает только FileNotFoundException, который, как я понимаю, это IOException, что является исключением. Может кто-нибудь объяснить, почему я поймаю FileNotFoundException или IOException вместо того, чтобы просто указывать общее "исключение" и не импортировать исключение (т. е. импортировать java.io.FileNotFoundException;)? Это только для удобства чтения?

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

изменить:--------------------

private BufferedReader askUserForFile(String prompt){
        BufferedReader rd = null;
        while(rd == null){
            try{
                String filename = readLine(prompt);
                rd = new BufferedReader( new FileReader(filename) );
            }
            catch(Exception e){
                println(e.getMessage());
            }
        }
        return rd;
    }

6 ответов


Exception является матерью всех исключений, включая все RuntimeException подклассы. Когда вы указываете поймать его, вы получите гораздо больше рыбы в сети, чем вы хотели, как NullPointerExceptions,IllegalArgumentExceptionS и так далее.

при ловле generic Exception и правильная вещь, которую нужно сделать в какой-то момент вашего кода, поймать его на любом нижнем уровне почти наверняка неправильно и может повредить поведению вашего приложения.

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


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

Если вы просто ловите Exception, тогда вы поймаете все эти другие ошибки, которые могут скрыть другую проблему. Также ваш код внутри блока catch не может предположить, что исключение произошло из-за исключения IOException, так как любое исключение будет поймано.


в качестве продолжения ответа dkatzel предположим, что вы начинаете читать из файла в том же блоке try, и файл сообщает вам, какое значение в массиве опций использовать:

String toPrint = {"Hi", "World", "I'm", "A", "String", "Array"};
try{
    BufferedReader reader = new BufferedReader( new FileReader("foo.bar") );
    String line = reader.readLine();
    System.out.println(toPrint[Integer.parseInt(line)]);

}
catch(Exception e){
    println( e.getMessage() );
}

теперь вы понятия не имеете, что на самом деле пошло не так, кроме как через трассировку стека. Вы не можете справиться с любыми исправимыми проблемами. Вы не можете сказать в коде, существует ли файл (FileNotFoundException), у вас нет доступа к файлу, (IOException), Если первая строка не была целым числом (NumberFormatException), или число было больше длины массива (ArrayIndexOutOfBoundsException). Если вы хотите напечатать значение по умолчанию, если вы не можете прочитать номер, вы можете вместо этого поймать NumberFormatException и распечатать значение вместо того, чтобы выходить из всей программы.

Я признаю, что это довольно надуманный пример, но он должен дать объяснение, почему ловить Exception - это плохо. У Марко также есть очень хороший ответ, заявив, что обычно лучше позволить исключению распространяться (особенно с RuntimeExceptions) чем к создайте кучу беспорядочного кода, пытаясь справиться с каждой проблемой, которая может произойти.


Что делать, если вы хотите сделать другое действие с разными исключениями? Вы можете сделать блок catch для IOException и, например, заставить его показать окно сообщения. Затем сделайте еще один блок catch для FileNotFoundException и заставьте его создать новый файл и попытаться открыть его снова или даже перестроить исключение. Надеюсь, я правильно объяснил. Ура!


причина в том, что всякий раз, когда вы программируете, вы должны думать обо всех возможностях, и это полезно сделать что-то для конкретной ошибки. Exception все Способ ловли ошибок и будет обрабатывать все исключения те же. IOException поймает любые исключения ввода-вывода, поэтому он будет обрабатывать файл не найден и другие исключения ввода-вывода (например,EOFException) то же самое. FileNotFoundException будет только поймать файл не найден исключения, поэтому вы можете обрабатывать его вместо того, чтобы просто регистрировать его.

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


FileNotFoundException это IOException что это Exception

вы правы. Но если вы поймаете Exception объекты, которые вы поймаете любой исключение, вызванное вашим кодом, а не только FileNotFound исключения.

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

try {
    /*
     * Code, code and more code
     */
} catch(ExceptionType1 e) {
        System.err.println("Something went wrong! It is a type 1 exception");
} catch(ExceptionType2 e) {
        System.err.println("Something went wrong! It is a type 2 exception");
} catch(Exception e) {
        System.err.println("Something went wrong! It is not any of the known exception types");
}

сравнить возможности с этого:

try {
    /*
     * Code, code and more code
     */
} catch(Exception e) {
        System.err.println("Something went wrong! Can be exception type 1, 2 or something else");
}

как вы можете видеть, дифференцирование типов исключений может помочь вам понимаю, что пошло не так в коде.