Как обрабатывать несколько исключений в методе Java?
Я читал, что это не лучшая практика для обработки нескольких исключений, как это:
public void myMethod() throws ExceptionA, ExceptionB, ExceptionC {
//more code here
}
А затем вызвать myMethod():
try {
myObject.myMethod();
} catch(Exception e) {
//More code here
}
Несмотря на то, что исключение является родительским классом для всех других исключений, это считается плохой практикой. Но в моем приложении я использую Java 6 и мне нужно:
- Делать файловые операции, которые могут подразумевать исключение FileNotFOundException и IOException
- Объекты Marshal (для создания файлов XML) JAXBException
- Создайте файл pdf (используя библиотеку pdfbox) COSVisitorException
- Отправить письмо с помощью JavaMail, MessagingException
Самый простой способ - добавить оператор throws в объявление метода, но что может быть правильным для написания метода клиента?
Можно ли добавить 6 или 7 блоков catch для обработки всех возможных исключений?
1 ответ
Вообще говоря (для Java 6 и ниже), вы должны обрабатывать каждое исключение индивидуально...
try {
myObject.myMethod();
} catch (ExceptionA e) {
// Condition for A
} catch (ExceptionB e) {
// Condition for B
} catch (ExceptionC e) {
// Condition for C
}
Это позволяет вам обрабатывать каждое исключение по-разному в зависимости от того, что это такое, но также означает, что вы обрабатываете только те исключения, о которых было сообщено, что метод
В Java 7+ вы можете использовать "multi-catch" или "комбинированный catch" (мы не можем найти "официальный" термин)
try {
myObject.myMethod();
} catch (ExceptionA | ExceptionB | ExceptionC e) {
// Condition for A and B and C
}
Но даже тогда вы должны сосредоточить исключения в "общих" группах использования.
try {
myObject.myMethod();
} catch (ExceptionA | ExceptionB e) {
// Condition for A and B
} catch (ExceptionC e) {
// Condition for C
}
Другой вариант, если вы контролируете, как определяются исключения, заключается в расширении из общего базового исключения, хорошим примером этого является FileNotFoundException
который простирается от IOException
, который брошен FileReader
а также FileInputStream
(в качестве примера), это означает, что вы можете обрабатывать FileNotFoundException
как обычный IOException
если вы хотите...
FileReader fr = null;
try {
fr = new FileReader(new File(...));
// Read from reader...
} catch (IOException exp) {
// Common catch block
} finally {
// Best attempt to close
try {
fr.close();
} catch (Exception exp) {
}
}
Или вы могли бы справиться с FileNotFoundException
как это собственное состояние...
FileReader fr = null;
try {
fr = new FileReader(new File(...));
// Read from reader...
} catch (FileNotFoundException exp) {
// File not found condition
} catch (IOException exp) {
// Other IO condition
} finally {
// Best attempt to close
try {
if (fr != null) {
fr.close();
}
} catch (Exception exp) {
}
}
Это позволяет вам сгруппировать "похожие" исключения вместе, но также предоставляет вам элемент управления для определения более точных условий, если вам нужно...
Осторожно, хотя, приведенный выше пример, если я поставлю IOException
во-первых, FileNotFoundException
никогда не будет обрабатываться, при этом убедитесь, что вы используете сначала самые низкие / самые трудные / лучшие исключения, так как они обрабатываются последовательно в указанном вами порядке
Другой вариант (который я не очень заинтересован, но видел) может заключаться в том, чтобы поймать "общего" предка и затем сравнить фактический тип, что позволит вам предоставить общие обработчики для некоторого подтипа исключения.
} catch (IOException exp) {
if (exp instanceof FileNotFound || exp instanceof FileSystemException) {
// Common handling
} else {
// Generic handling
}
}
Это может быть полезно в ситуациях, когда метод выбрасывает только тип предка (т.е. IOException
), но вам нужно предоставить более детальное разрешение
Но, опять же, я бы сфокусировался только на обработке ожидаемых "общих" исключений, объявленных как брошенные, не зацикливайтесь на ловле Throwable
например