Могу ли я перехватить несколько исключений Java в одном предложении catch? - PullRequest
645 голосов
/ 16 августа 2010

В 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();
}

Есть ли способ сделать это?

Ответы [ 9 ]

1050 голосов
/ 16 августа 2010

Это стало возможным начиная с 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
102 голосов
/ 28 августа 2012

Не совсем до 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();
}
23 голосов
/ 16 августа 2010

В Java 7 вы можете определить несколько предложений catch, например:

catch (IllegalArgumentException | SecurityException e)
{
    ...
}
15 голосов
/ 16 августа 2010

Нет, по одному на каждого клиента.

Вы можете поймать суперкласс, например java.lang.Exception, если вы выполняете одно и то же действие во всех случаях.

try {
    // some code
} catch(Exception e) { //All exceptions are caught here as all are inheriting java.lang.Exception
    e.printStackTrace();
}

Но это не лучшая практика. Вы должны ловить исключение только тогда, когда у вас есть стратегия для его фактической обработки - а регистрация и повторная обработка не являются «обработкой». Если у вас нет корректирующего действия, лучше добавьте его в сигнатуру метода и дайте всплыть тому, кто может справиться с ситуацией.

13 голосов
/ 16 августа 2010

Если существует иерархия исключений, вы можете использовать базовый класс для перехвата всех подклассов исключений. В вырожденном случае вы можете перехватить все исключения 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 ) { 
  ...
}
10 голосов
/ 19 октября 2013

Более чистая (но менее многословная, и, возможно, не столь предпочтительная) альтернатива ответу пользователя user454322 на Java 6 (т.е. Android) будет заключаться в том, чтобы перехватить все Exception s и повторно выдать 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.

3 голосов
/ 16 февраля 2015

В до-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.
  }
0 голосов
/ 31 июля 2018

Да. Вот способ с использованием разделителя труб (|),

try
{
    .......
}    
catch
{
    catch(IllegalArgumentException | SecurityException | IllegalAccessException | NoSuchFieldException e)
}
0 голосов
/ 16 августа 2010

Поймать исключение, которое оказывается родительским классом в иерархии исключений. Это, конечно, плохая практика .В вашем случае общим родительским исключением является класс Exception, и перехват любого исключения, которое является экземпляром Exception, действительно является плохой практикой - исключения, такие как NullPointerException, обычно являются ошибками программирования и обычно должны решаться путем проверки нулевых значений.

...