2013-07-01 38 views
2

的結束我有一個類Game與以下簽名的構造函數:Java不考慮失敗的方法分支

public Game(String[] boardState) throws InvalidStringsInputException, WrongNumberOfMarksException 

並且在junit4測試用例的方法:

public static Game newGameFromStringsSuccessful(String[] input) //it is the line 9 
{ 
    try 
    { 
     return new Game(input); 
    } 
    catch (WrongNumberOfMarksException exception) 
    { 
     fail("Caught exception where it shouldn't be"); 
    } 
    catch (InvalidStringsInputException exception) 
    { 
     fail("Caught exception where it shouldn't be"); 
    } 
} 

我使用Eclipse和它爲我的錯誤: This method must return a result of type Game line 9 Java Problem

如果我插入兩個兩端塊,錯誤消失,但我的問題沒有:爲什麼即使在調用fail()方法後,java也想要它?

+0

下面的答案涵蓋了如何避免這種情況。不過,我認爲重要的是要注意這可能是一個糟糕的設計。我不認爲你需要在這裏拋出異常,你應該確保input []永遠不會失效。或者如果這是不可能的,在構造函數中有一個默認設置可以重新使用。 – MaxAlexander

+0

@MaxAlexander我需要那些防禦性編程的例外。 – CrabMan

回答

3

why does java want it even after fail() method is called?

因爲編譯器不知道fail無法正常返回。在Java中沒有辦法表達。 fail消息調用的結尾仍然是可達 - 因此該方法的結尾也是可到達的。

假設在fail方法中存在一個錯誤,所以最後您達到了方法的結尾 - 您會期望發生什麼?

最簡單的解決方法是在方法的末尾拋出一些運行時異常, AssertionError

throw new AssertionError("fail must have returned normally!"); 

它基本上是一個例外,說:「這個世界太瘋狂了,我不想在這裏再住」 - 這也使編譯器高興,因爲該方法的右括號不再到達。

另一種選擇 - 不提供在這裏,因爲你不控制fail方法 - 將申報fail方法返回某種運行時異常的,此時你的catch塊看起來是這樣的:

catch (InvalidStringsInputException exception) 
{ 
    throw fail("Caught exception where it shouldn't be"); 
} 

當然實施fail仍然會拋出異常,而不是返回它,但它意味着編譯器知道這是catch塊是絕對不會正常完成。

1

Jon的回答如下解釋了編譯器爲什麼抱怨。但是,我建議避免這種情況的正確方法是不要在您測試中使用try/catch。只要讓異常在調用堆棧中傳播出去,然後再進行測試。 JUnit會抓住它並在測試失敗的同時提供拋出異常的整個堆棧跟蹤。

或者,如果您不想傳播throws子句,請將該異常包裝在RuntimeException中,然後拋出該異常。同樣,這將提供堆棧跟蹤以允許更好的診斷。