2009-11-25 54 views
2

假设InvalidResourceException是ResourceException的一个子类。定义了两种方法:Java的catch块使用静态绑定?

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

现在下面的代码:

打印此:

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): 
} 
+0

这种行为对我来说似乎很有用。 – 2009-11-25 19:36:12

回答

11

是。这是正确的。重载总是静态解析的。

你后面的两个例子都不会编译为e的静态类型是Exception,并且你的重载都不接受这种类型。

编辑:

请注意,您的最后一个例子是不是一个真正的直接模拟到try/catch块。在try/catch中,有两个变量叫做e:每个catch有一个变量,它们的静态类型分别为InvalidResourceExceptionResourceException。在最后一个例子中,您有一个名为e的变量,其静态类型为Exception。如果你添加了新的变量并通过一个强制类型赋值给它们,那么你会得到和你的try/catch一样的行为(尽管你不得不失去最后的else分支)。

+0

解决重载问题比简单地称为“静态”要复杂一点 - 还有一个动态的方面。有关详细信息,请参见。 – 2009-11-25 20:00:03

+0

*方法调用*(链接到的JLS的部分)有一个动态方面,但*重载决策*是严格静态的(即:编译时)操作。实际上,您链接的JLS的一部分支持这一点:唯一提到过载的部分(其他概述在开头)是§15.12.2,“编译时间步骤2:确定方法签名”。 – 2009-11-25 20:18:42

1

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

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

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

最后一部分也会因第三部分的原因而无法编译。

0

您正在等待java不支持的名为“double dispatch”的内容。