我有一个类Game
,其构造函数具有以下签名:
public Game(String[] boardState) throws InvalidStringsInputException, WrongNumberOfMarksException
junit4 testcase中有一个方法:
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
如果我在两个return null
块的末尾插入catch
,则错误消失,但我的问题不是:为什么java甚至在调用fail()方法后仍然需要它?
答案 0 :(得分:3)
为什么即使在调用fail()方法之后java也想要它?
因为编译器不知道 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 :(得分:1)
Jon的回答解释了为什么编译器抱怨。但是,我建议避免这种情况的正确方法是在测试中没有try/catch
。只是让异常在调用堆栈中传播并超出测试范围。 JUnit将捕获它并在测试失败的同时提供抛出异常的整个堆栈跟踪。
或者,如果您不想传播throws
子句,请将异常包装在RuntimeException
中,然后将其抛出。同样,这将提供堆栈跟踪以便更好地进行诊断。