2009-11-25 48 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」的內容。