Могу ли я перехватить несколько исключений 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и перебросить RuntimeExceptions. Это не сработает, если вы планируете перехватывать другие типы исключений дальше по стеку (если только вы не перезапускаете их), но будет эффективно перехватывать все проверенные исключения.

Например:

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
                }
                
                 }
Другие вопросы по тегам