我之前从未做过任何严肃的Java编码,但我根据现有技能(Delphi和C#)学习了语法,库和概念.我很难理解的一件事是,我已经看到了这么多代码,在printStackTrace这样的情况下默默地消耗异常:
public void process() {
try {
System.out.println("test");
} catch(Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
在我遇到的几乎所有Java文章和项目中都有类似的代码.根据我的知识,这是非常糟糕的.几乎总是应该将异常转发到外部上下文,如下所示:
public void process() {
try {
System.out.println("test");
} catch(Exception e) {
e.printStackTrace();
throw new AssertionError(e);
}
}
Run Code Online (Sandbox Code Playgroud)
大多数情况下,异常最终应该在属于底层框架的最外层循环中处理(例如Java Swing).为什么Java世界中的代码看起来像这样的规范?我很困惑.
根据我的背景,我宁愿完全删除printStackTrace .我会简单地重新抛出一个未处理的aka RuntimeException(或更好的AssertionError),然后捕获并在最合适的位置记录它:框架最外层循环.
public void process() {
try {
System.out.println("test");
} catch(Exception e) {
throw new AssertionError(e);
}
}
Run Code Online (Sandbox Code Playgroud) 我想抓住我期望的例外,但允许其他人通过.
我现在遇到的解决方案是:
protected void perfromCall(Class expectedException) throws Exception {
try {
response = call.call(request);
} catch (Exception e) {
if (!expectedException.isInstance(e)) {
throw new Exception(e);
}
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这会默默地吃掉我想要的预期异常并扔掉其他异常,但是我不喜欢的是它包装了意外的异常,现在我必须在调用者中捕获意外而不是之前(在尝试静默捕获之前)预期的异常)我可以让它们冒泡到测试框架以使测试失败.
是否有一种更清晰的方式来说"我期望A类的异常,但对于任何其他异常,让它被抛到链上直到它由上面的测试框架处理"?
编辑:我想提供一些理由,说明为什么我要这样做,因为有一些答案(现已删除)质疑默默地吃异常.这适用于调用服务的测试框架.一些测试将错误的参数传递给服务,因此他们期望服务因捕获无效请求而抛出异常.因此,我想默默地吃掉预期的异常,但仍然让意外的异常冒泡并且测试失败.