我可以捕获多个Java异常在同一个捕获子句?

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

有什么办法可以做到吗?

620687 次浏览

不,在Java7之前每位顾客一张。

您可以捕获超类,如java.lang.Exception,只要您在所有情况下都采取相同的操作。

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

但这可能不是最佳实践。只有当你有实际处理它的策略时,你才应该捕获异常——并且记录和重新抛出不是“处理它”。如果你没有纠正措施,最好将其添加到方法签名中,让它冒泡给能够处理这种情况的人。

使用JDK 7及更高版本,您可以这样做:

try {...} catch (IllegalArgumentException | SecurityException | IllegalAccessException | NoSuchFieldException e) {someCode();}

这当然是不好的做法。在您的情况下,常见的父异常恰好是Exception类,并且捕获任何作为Exception实例的异常确实是不好的做法-像NullPointerException这样的异常通常是编程错误,通常应该通过检查空值来解决。

这是可能的7Java。多捕获块的语法是:

try {...} catch (IllegalArgumentException | SecurityException | IllegalAccessException |NoSuchFieldException e) {someCode();}

但是请记住,如果所有异常都属于相同的类层次结构,您可以简单地捕获该基本异常类型。

另请注意,如果ExceptionB直接或间接地从ExceptionA继承,您无法在同一个块中捕获ExceptionAExceptionB。编译器会抱怨:

Alternatives in a multi-catch statement cannot be related by subclassingAlternative ExceptionB is a subclass of alternative ExceptionA

解决这个问题的方法是只在异常列表中包含祖先异常,因为它也会捕获子代类型的异常。

如果有异常层次结构,您可以使用基类来捕获异常的所有子类。在退化情况下,您可以使用以下命令捕获所有Java异常:

try {...} catch (Exception e) {someCode();}

在更常见的情况下,如果RepositoryException是基类,PathNotFoundException是派生类,则:

try {...} catch (RepositoryException re) {someCode();} catch (Exception e) {someCode();}

上面的代码将捕获RepositoryException和PathNotFoundException以进行一种异常处理,并且所有其他异常都集中在一起。自Java7日以来,根据@OScarRyz上面的回答:

try {...} catch( IOException | SQLException ex ) {...}

在Java7中,您可以定义多个catch子句,例如:

catch (IllegalArgumentException | SecurityException e){...}

不是在Java7之前,但是,我会这样做:

Java6及之前

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



Java7

try {//.....} catch ( IllegalArgumentException | SecurityException |IllegalAccessException |NoSuchFieldException exc) {someCode();}

user454322在Java6(即Android)上的答案的一个更简洁(但不那么冗长,也许不是首选)的替代方案是捕获所有Exception并重新抛出RuntimeException。如果你打算在堆栈的更高层捕获其他类型的异常(除非你也重新抛出它们),这将不起作用,但会有效地捕获所有检查异常。

例如:

try {// CODE THAT THROWS EXCEPTION} catch (Exception e) {if (e instanceof RuntimeException) {// this exception was not expected, so re-throw itthrow e;} else {// YOUR CODE FOR ALL CHECKED EXCEPTIONS}}

话虽如此,为了冗长,最好设置一个布尔值或其他一些变量,并在此基础上在try-cat块之后执行一些代码。

在pre-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.}

对于kotlin,目前还不可能,但他们已经考虑添加它:来源
但现在,只是一个小把戏:

try {// code} catch(ex:Exception) {when(ex) {is SomeException,is AnotherException -> {// handle}else -> throw ex}}

它非常简单:

try {// Your code here.} catch (IllegalArgumentException | SecurityException | IllegalAccessException |NoSuchFieldException e) {// Handle exception here.}