2008-11-21 66 views
9

在Java中,雙方法有什麼區別?Declare-and-throw與throw-without-being-being-declared例外

public void methodA() throws AnException { 
    //do something 
    throw new AnException(); 
} 

public void methodA() { 
    //do the same thing 
    throw new AnException(); 
} 

我有一個直覺,它是與作爲一個精心設計的方法(因爲我把了methodA在一個接口,宣佈它了methodA *確實在其實施的方式,從Java收到一個警告, 「A *不能重寫A,因爲A *不會拋出AnException」)。

這種推測是否正確?

在做事情的兩種方式中是否還有其他微妙的內涵?

回答

13

如果AnException是一個檢查異常(換句話說,如果它不擴展RuntimeException),那麼methodA將不會編譯。檢查的異常必須始終被降級。

如果AnException是一個未經檢查的異常(如果它確實擴展了RuntimeException),則java編譯器允許這兩者之一,並且由java運行時等效解釋。方法A在這種情況下仍然可能仍然是首選,因爲文檔的原因。您的方法的javadoc將顯示它可能拋出AnException。讓方法的用戶知道他們應該期待什麼異常是很好的。

+0

您似乎將這兩個示例都稱爲「methodA」,這有點令人困惑。 – Stephan 2013-11-25 06:07:35

0

在第二種方法中,AnException類需要是RuntimeException的子類,這意味着聲明不是必需的,方法調用者不必處理它。 RuntimeException的一個示例是ArrayOutOfBoundException,想象一下,如果每次使用List時都要顯式處理異常(通過聲明一個throws或try/catch塊)。

0

純粹由於文檔原因,函數定義中包含異常是很好的。通過這種方式,調用者很清楚需要處理哪些異常。我也猜測編譯器需要爲拋出異常的函數做一些高級設置。

1

必須在try catch塊或方法聲明拋出中調用第一個方法AnException 否則編譯將失敗。

第二沒有這樣的限制

2
從他人的你的方法本身的compilability給出很好的答案

除此之外,還有在實現超類接口和重載方法的問題。

規則說你可以重載/實現一個方法,但是你不能將另外的異常聲明爲由原始方法簽名聲明的方法。要理解這一點,請考慮這個例子。

比方說,你正在使用某種形式的數據結構:

public abstract class AbstractBox { 
    public abstract void addItem(Item newItem); 
    public abstract void removeItem(Item oldItem); 
} 

你有你自己的實現,但你決定聲明不會出現在原始簽名例外:

public class MyBox extends AbstractBox { 
    public void addItem(Item newItem) throws ItemAlreadyPresentException {...} 
    public void removeItem(Item oldItem) throws NoSuchItemException {...} 
} 

現在讓我們考慮處理Box對象的這個通用代碼,並接收MyBox的一個實例:

public void boxHandler(AbstractBox box) { 
    Item item = new Item(); 
    box.removeItem(item); 
} 

編寫此代碼的人不期待任何異常,也不打算處理實現或異常。爲了防止這種情況,編譯器將不允許您爲原始簽名中的那些聲明額外的例外。

當然,如果你處理內部異常......嗯,編譯器會很樂意讓你從你的簽名;-)

希望這有助於降聲明異常......

Yuval = 8-)

+0

你不能聲明或拋出額外的檢查異常。但是,您可以拋出額外的未聲明的未檢查的異常和錯誤。 – 2009-03-22 19:55:25