在Java中是否可以在同一个catch块中捕获两个异常?

Is it possible in Java to catch two exceptions in the same catch block?

本问题已经有最佳答案,请猛点这里访问。

我需要捕获两个异常,因为它们需要相同的处理逻辑。我想做如下的事情:

1
2
3
catch (Exception e, ExtendsRuntimeException re) {
    // common logic to handle both exceptions
}

是否可以避免在每个catch块中重复处理程序代码?


Java 7及其后

支持多个异常捕获,从Java 7开始。

语法是:

1
2
3
4
5
try {
     // stuff
} catch (Exception1 | Exception2 ex) {
     // Handle both exceptions
}

ex的静态类型是列出的异常中最专门化的通用父类型。有一个很好的特性,如果您在catch中重新执行ex,编译器知道只能抛出列出的异常之一。

Java 6及其更早

在Java 7之前,有一些方法来处理这个问题,但是它们往往是不雅的,并且有局限性。

接近1

1
2
3
4
5
6
7
8
9
10
11
try {
     // stuff
} catch (Exception1 ex) {
     handleException(ex);
} catch (Exception2 ex) {
     handleException(ex);
}

public void handleException(SuperException ex) {
     // handle exception here
}

如果异常处理程序需要访问在try之前声明的局部变量,这会变得混乱。如果handler方法需要重新引发异常(并且检查了异常),那么签名就会遇到严重的问题。具体地说,handleException必须宣布为投掷SuperException…这可能意味着您必须更改封闭方法的签名,等等。

接近2

1
2
3
4
5
6
7
8
9
try {
     // stuff
} catch (SuperException ex) {
     if (ex instanceof Exception1 || ex instanceof Exception2) {
         // handle exception
     } else {
         throw ex;
     }
}

再一次,我们在签名方面有一个潜在的问题。

接近3

1
2
3
4
5
6
7
try {
     // stuff
} catch (SuperException ex) {
     if (ex instanceof Exception1 || ex instanceof Exception2) {
         // handle exception
     }
}

如果省略了else部分(例如,因为目前没有SuperException的其他子类型),代码就会变得更脆弱。如果重新组织异常层次结构,没有else的这个处理程序可能会以静默方式接收异常!


Java<= 6 .x只允许您捕获每个catch块中的一个异常:

1
2
3
4
5
6
7
try {

} catch (ExceptionType name) {

} catch (ExceptionType name) {

}

文档:

Each catch block is an exception handler and handles the type of
exception indicated by its argument. The argument type, ExceptionType,
declares the type of exception that the handler can handle and must be
the name of a class that inherits from the Throwable class.

对于Java 7,可以在一个catch块上捕获多个异常:

1
2
3
4
catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

文档:

In Java SE 7 and later, a single catch block can handle more than one
type of exception. This feature can reduce code duplication and lessen
the temptation to catch an overly broad exception.

参考文献:http://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html


如果不在Java 7上,则可以将异常处理提取到方法——这样可以至少最小化复制。

1
2
3
4
5
try {
   // try something
}
catch(ExtendsRuntimeException e) { handleError(e); }
catch(Exception e) { handleError(e); }


在JavaSE 7启动之前,我们习惯于用多个catch语句编写代码,与一个尝试块相关。一个非常基本的例子:

1
2
3
4
5
6
 try {
  // some instructions
} catch(ATypeException e) {
} catch(BTypeException e) {
} catch(CTypeException e) {
}

但是现在使用Java的最新更新,而不是编写多个catch语句,我们可以处理单个catch子句中的多个异常。下面是一个示例,说明如何实现此功能。

1
2
3
4
5
try {
// some instructions
} catch(ATypeException|BTypeException|CTypeException ex) {
   throw e;
}

因此,单个catch子句中的多个异常不仅简化了代码,而且减少了代码的冗余。我发现这篇文章很好地解释了这个特性及其实现。从Java 7改进和改进异常处理这对你也有帮助。


对于Java< 7,可以使用if除异常之外:

1
2
3
4
5
6
7
8
9
10
11
12
try {
    // common logic to handle both exceptions
} catch (Exception ex) {
    if (ex instanceof Exception1 || ex instanceof Exception2) {

    }
    else {
        throw ex;
        // or if you don't want to have to declare Exception use
        // throw new RuntimeException(ex);
    }
}

编辑并替换了可丢弃的。


http://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html包含在同一块中捕获多个异常。

1
2
3
4
5
 try {
     // your code
} catch (Exception1 | Exception2 ex) {
     // Handle 2 exceptions in Java 7
}

我在做学习卡,这条线很有用,只想放进我的两分钱。