В Java, в чем разница между перехватом универсального исключения и конкретного исключения (например, IOException?) - PullRequest
10 голосов
/ 12 мая 2011

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

Ответы [ 7 ]

16 голосов
/ 12 мая 2011

Разница между выполнением общего оператора try / catch и перехватом определенного исключения (например, FileNotFoundException) обычно зависит от того, какие ошибки нужно обработать, и о каких ошибках не нужно беспокоиться.Например:

catch (Exception e) {    //A (too) general exception handler
...
}

Приведенный выше код будет перехватывать КАЖДОЕ исключение, которое выдается внутри оператора try.Но, может быть, вы не хотите обрабатывать каждую ошибку.Что вы можете сделать с исключением «OutOfMemory»?

Лучшим методом обработки ошибок было бы выполнение некоторого действия по умолчанию, если ошибка неизвестна или что-то, с чем вы ничего не можете сделать, и выполнение другого действия, если вы обнаружите, что можете выполнить «План Б», есливы ловите.

Например, предположим, что вы пытаетесь открыть файл, но файл не существует.Вы можете поймать FileNotFoundException и создать новый пустой файл, как показано ниже:

catch (FileNotFoundException e) {    //A specific exception handler
    //create a new file and proceed, instead of throwing the error to the user
}catch (Exception e) {    //For all other errors, alert the user
    ...
}

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

3 голосов
/ 12 мая 2011

Улавливание определенных исключений позволяет адаптировать конкретные ответы для каждого случая.

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

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

В некоторых случаях сложность некоторых базовых API требует как обработки всех различных исключений , так и извлечения структуры try-catch в служебный метод. Например, кажется, что вызов метода через отражение регулярно требует наличия API фасадов.

На уровне разработки API всегда существует баланс между

  • Очень богатая (общедоступная) иерархия исключений
  • Включение кодов ошибок как часть информации, содержащейся в некотором базовом исключении, и
  • Публичный набор интерфейсов маркеров и использование личных подтипов исключений
2 голосов
/ 12 мая 2011

Хороший пример, который показывает способность обрабатывать проблемы в зависимости от типа возникшей проблемы:

try {
  // open a file based on its file name
} catch (FileNotFoundException e) {
  // indicate that the user specified a file that doesn't exist.
  // reopen file selection dialog box.
} catch (IOException e) {
  // indicate that the file cannot be opened.
}

при соответствующем:

try {
  // open a file based on its file name.
} catch (Exception e) {
  // indicate that something was wrong
  // display the exception's "reason" string.
}

Последний пример не предоставляет средств для обработки исключения в зависимости от возникшей проблемы. Все проблемы решаются одинаково.

1 голос
/ 12 мая 2011

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

    public String readFile(File file) {
        try {
            Reader r = new FileReader(file);
            // read file
            return ...;  // the file contents
        } catch (Exception ex) {
            // file not found ...
            return "";
        }
    }

Как видите, вышеприведенное написано в предположении, что единственный способ, которым код внутри try может дать сбой, - это если файл отсутствует или не может бытьоткрыт по какой-то причине.Фактически, если метод вызывается с файлом null или если в коде, который читает файл, есть какая-то ошибка, возможны NPE и другие непроверенные исключения.Таким образом, код будет скрывать ошибки, перехватывая Exception.

. Правильная версия приведенного выше кода перехватит IOException (или, возможно, FileNotFoundException) и позволит распространяться неожиданным исключениям.

1 голос
/ 12 мая 2011

Возьмите этот пример:

try {
 StringBuffer fileData = new StringBuffer(1000);
 BufferedReader reader = new BufferedReader(
   new FileReader(filePath));
 char[] buf = new char[1024];
 int numRead=0;
 while((numRead=reader.read(buf)) != -1){
   fileData.append(buf, 0, numRead);
 }
 reader.close();
 return fileData.toString();
} catch (Exception e) {
 //do something generic - maybe log it
}

Как есть, работает ... обычно. Однако, с расплывчатой ​​ошибкой, я не могу ничего сделать, кроме как предупредить пользователя. Если бы я поймал FileNotFoundException специально, я мог бы попробовать другой файл. Если бы я поймал IOException специально, я мог бы предупредить о чем-то еще. Этот пример немного слаб, но может дать вам некоторое представление.

1 голос
/ 12 мая 2011

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

1 голос
/ 12 мая 2011

Если у вас есть блок кода, который может выдавать различные исключения, и вы окружаете его общей попыткой {} catch {Exception e}, вы не будете знать, что именно произошло и как вы должны обработать ошибку.

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