Java catch块使用静态绑定?

时间:2009-11-25 19:33:10

标签: java instanceof

假设InvalidResourceException是ResourceException的子类。定义两种方法:

void handleException(ResourceException e) {
  System.out.println("ResourceException " + e.toString());
}
void handleException(InvalidResourceException e) {
  System.out.println("InvalidResourceException " + e.toString());
}

现在输入以下代码:

try {
  throw new InvalidResourceException("invalid resource");
} catch (ResourceException e) {
  handleException(e);
}

打印出来:

ResourceException: com.myPackage.InvalidResourceException: invalid resource

但是以下代码:

   try {
     throw new InvalidResourceException("invalid resource");
   } catch (InvalidResourceException e) {
     handleException(e);
   } catch (ResourceException e) {
     handleException(e);
   }

打印出来:

InvalidResourceException:  com.myPackage.InvalidResourceException: invalid resource

这是Sun的JDK 1.5.0_15。

这是否符合Java标准?

这段代码应该做什么?

Exception e = new InvalidResourceException("invalid resource");
handleException(e);

这段代码应该做什么?

Exception e = new InvalidResourceException("invalid resource");
if (e instanceOf ResourceException) {
  handleException(e);
} else if (e instanceOf InvalidResourceException) {
  handleException(e);
} else {
  handleException(e):
}

3 个答案:

答案 0 :(得分:11)

是。这是正确的。过载总是静态解决。

后两个示例都不会编译为e的静态类型为Exception,并且您的任何重载都不接受该类型。

修改

请注意,您的最后一个示例实际上并不是try / catch块的直接模拟。在try / catch中,您有两个名为e的变量:每个catch一个,其静态类型分别为InvalidResourceExceptionResourceException。在最后一个示例中,您有一个名为e的变量,其静态类型为Exception。如果您添加了新变量并使用强制转换分配给它们,那么您将获得与try / catch相同的行为(尽管您必须丢失最后的其他分支)。

答案 1 :(得分:1)

关于问题的第一部分,调用的正确方法是在编译时根据变量声明的类型确定的。例如。如果你改变了catch语句以捕获InvalidResourceException,那么将调用handleException(InvalidResourceException)重载。

关于问题的第二部分,JVM只是找到能够处理抛出的异常的第一个catch语句。如果你要抛出一个ResourceException,那么第二个catch块就会被执行。

第三部分不会编译,因为没有合适的handleException()方法来处理普通的异常。

由于与第三部分相同的原因,最后一部分也将无法编译。

答案 2 :(得分:0)

你期待一种叫做“双重调度”的东西,这是java不支持的。