为什么订单在捕获异常时很重要?

use*_*033 24 java exception-handling

我不得不用一些代码回答这个问题:

假设我编写了以下方法规范:
public void manipulateData ( ) throws java.sql.SQLException, java.sql.SQLDataException

您正在编写将使用此方法的数据库程序的代码,并且您希望专门处理每个方法.try/catch子句应该是什么样的?
您可以使用no-ops-- empty blocks {} - 用于catch子句内容.
我们只对这里语句的语法和结构感兴趣.

我回答说:

try {

} catch(java.sql.SQLException e) {

}
catch(java.sql.SQLDataException e) {

}
Run Code Online (Sandbox Code Playgroud)

由于这个原因,他没有接受答案:

"你的捕获条款的顺序是错误的.你能解释为什么这个命令很重要吗?"

他的答案是否正确?

use*_*001 42

是的,他是对的.正如你在Javadoc中看到的那样,SQLDataException是一个子类SQLException.因此,您的答案是错误的,因为它会在第二个中创建一块无法访问的代码catch.

在Java中,此代码甚至不会编译.在其他语言(例如python)中,这样的代码会创建一个微妙的bug,因为SQLDataException实际上会在第一个块中捕获,而不是在第二个块中捕获(如果它不是子类的话就是这种情况).

如果你回答catch(java.sql.SQLException | java.sql.SQLDataException e) { },它仍然是不正确的,因为问题要求具体处理每个例外.

正确答案在Grijesh的回答中

  • @ratchetfreak是的.如果在编译时失败,则"异常java.sql.SQLDataException已被捕获".编译器足够聪明,可以检测到这一点.但即使编译器没有检测到它,它仍然是一个逻辑错误,因为第二个捕获将无法访问. (4认同)

Dig*_*ara 22

在Java中,您必须首先放置包含最少的Exception.接下来的例外必须更具包容性(当它们相关时).

例如:如果你把所有(最多)的包容性放在首位,那么永远不会调用下一个.像这样的代码:

try {
     System.out.println("Trying to prove a point");
     throw new java.sql.SqlDataException("Where will I show up?");
}catch(Exception e){
     System.out.println("First catch");
} catch(java.sql.SQLException e) {
     System.out.println("Second catch");
}
catch(java.sql.SQLDataException e) {
     System.out.println("Third catch");
}
Run Code Online (Sandbox Code Playgroud)

永远不会打印您希望打印的信息.

  • 并且编译器会对它感到生气. (5认同)
  • 那么,以后的例外并不总是*必须更具包容性; 仅在某些捕获的异常是其他异常的子类的情况下(如给出的示例中所示). (2认同)

Gri*_*han 6

由于以下原因,在捕获异常时订购事项:

记得:

  • 基类变量也可以引用子类对象.
  • e 是一个参考变量
catch(ExceptionType e){
}
Run Code Online (Sandbox Code Playgroud)

小写字符e是对抛出(和捕获)ExceptionType对象的引用.

您的代码未被接受的原因?

重要的是要记住异常子类必须在它们的超类之前.这是因为使用超类的catch语句将捕获该类型及其任何子类的异常.因此,如果它来自超类,则永远不会到达子类.
此外,在Java中,无法访问的代码是错误的.

SQLException 是超级类的 SQLDataException

   +----+----+----+
   | SQLException |  `e` can reference SQLException as well as SQLDataException
   +----+----+----+
          ^
          |
          |
+----+----+----+---+
| SQLDataException |   More specific 
+----+----+----+---+
Run Code Online (Sandbox Code Playgroud)

如果你的写作有错误 Unreachable code(阅读评论):

try{

} 
catch(java.sql.SQLException e){//also catch exception of SQLDataException type 

}
catch(java.sql.SQLDataException e){//hence this remains Unreachable code

}
Run Code Online (Sandbox Code Playgroud)

如果您尝试编译此程序,您将收到一条错误消息,指出第一个catch语句将处理所有基于SQLException的错误,包括SQLDataException.这意味着第二个catch语句永远不会执行.

正确的解决方案?

修复它反转catch语句的顺序.接下来是:

try{

} 
catch(java.sql.SQLDataException e){

}catch(java.sql.SQLException e){

}
Run Code Online (Sandbox Code Playgroud)


kbb*_*cks 5

SQLDataException永远不会被击中,因为它SQLException会在到达之前捕获任何SQL异常SQLDataException.

SQLDataException是一个子类SQLException


PhD*_*PhD 5

想想异常的继承层次结构:SQLDataException extends SQLException所以如果你首先捕获'泛型'(即层次结构中最顶层的基类),那么由于多态性,每个"低于"的东西都属于同一类型,即SQLDataException isa SQLException

因此,你应该在继承层次结构中以自下而上的顺序捕获它们,即,子类首先一直到(泛型)基类.这是因为catch条款是按照您声明它们的顺序进行评估的.