Могу ли я перехватить несколько исключений Java в одном предложении catch?
В Java я хочу сделать что-то вроде этого:
try {
...
} catch (/* code to catch IllegalArgumentException, SecurityException,
IllegalAccessException, and NoSuchFieldException at the same time */) {
someCode();
}
...вместо:
try {
...
} catch (IllegalArgumentException e) {
someCode();
} catch (SecurityException e) {
someCode();
} catch (IllegalAccessException e) {
someCode();
} catch (NoSuchFieldException e) {
someCode();
}
Есть какой-либо способ сделать это?
12 ответов
Это стало возможным начиная с Java 7. Синтаксис для блока multi-catch:
try {
...
} catch (IOException | SQLException ex) {
...
}
Помните, однако, что если все исключения принадлежат одной и той же иерархии классов, вы можете просто перехватить этот базовый тип исключения.
Также обратите внимание, что вы не можете перехватить и ExceptionA, и ExceptionB в одном и том же блоке, если ExceptionB наследуется, прямо или косвенно, от ExceptionA. Компилятор будет жаловаться:
Alternatives in a multi-catch statement cannot be related by subclassing
Alternative ExceptionB is a subclass of alternative ExceptionA
Не совсем до Java 7, но я бы сделал что-то вроде этого:
Java 6 и раньше
try {
//.....
} catch (Exception exc) {
if (exc instanceof IllegalArgumentException || exc instanceof SecurityException ||
exc instanceof IllegalAccessException || exc instanceof NoSuchFieldException ) {
someCode();
} else if (exc instanceof RuntimeException) {
throw (RuntimeException) exc;
} else {
throw new RuntimeException(exc);
}
}
Java 7
try {
//.....
} catch ( IllegalArgumentException | SecurityException |
IllegalAccessException |NoSuchFieldException exc) {
someCode();
}
Нет, по одному на каждого клиента.
Вы можете поймать суперкласс, такой как java.lang.Exception, если вы выполняете одно и то же действие во всех случаях.
try {
// some code
} catch(Exception e) { //All exceptions are caught here as all are inheriting java.lang.Exception
e.printStackTrace();
}
Но это не может быть лучшей практикой. Вы должны ловить исключение только тогда, когда у вас есть стратегия для его фактической обработки, а регистрация и повторная обработка не являются "обработкой". Если у вас нет корректирующего действия, лучше добавить его в сигнатуру метода и дать ему возможность всплыть кому-то, кто может справиться с ситуацией.
В Java 7 вы можете определить несколько предложений catch, таких как:
catch (IllegalArgumentException | SecurityException e)
{
...
}
Если существует иерархия исключений, вы можете использовать базовый класс для перехвата всех подклассов исключений. В вырожденном случае вы можете перехватить все исключения Java с помощью:
try {
...
} catch (Exception e) {
someCode();
}
В более распространенном случае, если RepositoryException является базовым классом, а PathNotFoundException является производным классом, тогда:
try {
...
} catch (RepositoryException re) {
someCode();
} catch (Exception e) {
someCode();
}
Приведенный выше код будет перехватывать RepositoryException и PathNotFoundException для одного вида обработки исключений, а все остальные исключения объединяются. Начиная с Java 7, согласно ответу @OscarRyz выше:
try {
...
} catch( IOException | SQLException ex ) {
...
}
Более чистая (но менее многословная и, возможно, не столь предпочтительная) альтернатива ответу пользователя user454322 на Java 6 (т.е. Android) будет заключаться в том, чтобы поймать все Exception
и перебросить RuntimeException
s. Это не сработает, если вы планируете перехватывать другие типы исключений дальше по стеку (если только вы не перезапускаете их), но будет эффективно перехватывать все проверенные исключения.
Например:
try {
// CODE THAT THROWS EXCEPTION
} catch (Exception e) {
if (e instanceof RuntimeException) {
// this exception was not expected, so re-throw it
throw e;
} else {
// YOUR CODE FOR ALL CHECKED EXCEPTIONS
}
}
Это, как говорится, для многословия, возможно, было бы лучше установить логическую или некоторую другую переменную и на основе этого выполнить некоторый код после блока try-catch.
Для котлина это пока невозможно, но они решили добавить его: Источник
А пока небольшая хитрость:
try {
// code
} catch(ex:Exception) {
when(ex) {
is SomeException,
is AnotherException -> {
// handle
}
else -> throw ex
}
}
В до 7 как насчет:
Boolean caught = true;
Exception e;
try {
...
caught = false;
} catch (TransformerException te) {
e = te;
} catch (SocketException se) {
e = se;
} catch (IOException ie) {
e = ie;
}
if (caught) {
someCode(); // You can reference Exception e here.
}
Это очень просто:
try {
// Your code here.
} catch (IllegalArgumentException | SecurityException | IllegalAccessException |
NoSuchFieldException e) {
// Handle exception here.
}
Да. Вот способ с использованием разделителя трубы ( |),
try
{
.......
}
catch
{
catch(IllegalArgumentException | SecurityException | IllegalAccessException | NoSuchFieldException e)
}
Поймать исключение, которое оказывается родительским классом в иерархии исключений. Это, конечно, плохая практика. В вашем случае общим родительским исключением является класс Exception, и перехват любого исключения, являющегося экземпляром Exception, действительно является плохой практикой - исключения, такие как NullPointerException, обычно являются ошибками программирования и обычно должны решаться путем проверки нулевых значений.
в Котлине этот способ может быть полезен:
var result = false
try { ...
result=false
}catch (ex:Exception ){
when (ex) {
is SocketTimeoutException,
is NetworkOnMainThreadException,
is UnknownHostException,
is IllegalThreadStateException -> result=false
else -> throw ex
}
}