#java #exception
#java #исключение
Вопрос:
В настоящее время я перехватываю только общие исключения, но я хочу изменить это, чтобы перехватывать конкретные исключения, но в чем преимущество этого?
Ответ №1:
Разница между выполнением общего оператора 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
...
}
Это был самый эффективный и удобный для пользователя метод проверки ошибок, который я использовал в прошлом.
Комментарии:
1. конструктивный ответ на вопрос, который я искал. Я не вижу преимуществ в использовании общего исключения, отличного от предоставленного вами.
2. «OutOfMemory» является ошибкой и попадает под throwable, а не под Exception !
Ответ №2:
Перехват конкретных исключений позволяет адаптировать конкретные ответы к каждому случаю.
На логическом уровне серия блоков catch — это то же самое, что иметь один блок catch, а затем писать свою собственную условную логику внутри одного блока catch. Обратите внимание, что условная логика также должна была бы привести исключение к определенным подтипам, если вы хотите получить доступ к подробной информации, объявленной в пределах подтипа.
Несколько недостатков перехвата каждого исключения по отдельности включают в себя то, что вся структура try — catch становится очень большой и усложняет логику содержащего метода, а также необходимость повторять код во многих или всех отдельных блоках catch (например, протоколирование исключения).
В определенных случаях сложность некоторого базового API требует как обработки всех различных исключений, так и извлечения структуры try-catch в служебный метод. Например, вызов метода через отражение, по-видимому, регулярно требует наличия интерфейсных API.
На уровне разработки API всегда существует баланс между
- Очень богатая (общедоступная) иерархия исключений
- Включение кодов ошибок как части информации, содержащейся в некотором базовом исключении, и
- Общедоступный набор интерфейсов маркеров и использование частных подтипов исключений
Ответ №3:
Хороший пример, который показывает способность обрабатывать проблемы в зависимости от типа возникшей проблемы:
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.
}
Последний пример не предоставляет средств для обработки исключения на основе того, какая проблема возникла. Все проблемы обрабатываются одинаково.
Ответ №4:
Если у вас есть блок кода, который может генерировать разные исключения, и вы окружаете его общим try {} catch {Exception e} , вы не будете знать, что именно произошло и как вы должны обработать ошибку.
Ответ №5:
Если вы планируете, что вашим приложением будут пользоваться несколько человек, наличие определенных исключений позволит вам точно знать, где произошел сбой вашей программы, когда она находилась под контролем кого-то другого. но помимо этого, если программа предназначена только для вас, вы можете просто запустить ее через отладчик, хотя иметь привычку делать очень описательную и однозначную обработку ошибок — это здорово, если вы когда-нибудь планируете распространять свое программирование в массы 🙂
Ответ №6:
Возьмем этот пример:
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
конкретно, я мог бы предупредить о чем-то другом. Этот пример немного слабоват, но он может дать вам некоторое представление.
Ответ №7:
Проблема с перехватом общих исключений заключается в том, что вы в конечном итоге перехватываете (и часто неправильно обрабатываете) неожиданное исключение. Например:
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
) и позволит неожиданным исключениям распространяться.