我有一个使用两种API方法的应用程序。这两种方法都抛出超过五个例外。所以,如果我只是添加一个throws声明,那么它将成为一个超过十个的列表。 (我的方法无法处理任何十个例外)
我读过,抛出一长串异常是一种不好的做法。抛出(伞)异常是一种不好的做法。所以我该怎么做?
修改:添加了选择5.
答案 0 :(得分:2)
“2。创建自定义异常类”,但不是全部。在逻辑组中包装异常。例如,您可以XmlWritingException
,PaymentGatewayException
和DataAccessException
根据方案包装不同的例外。
甚至可以(并且首选)将相同的异常包装在不同的包装器中。例如,如果由于通信问题导致付款失败,您可以在IOException
中包裹PaymentGatewayException
,但如果在使用xml进行某些i / o操作时失败,则可以在XmlWritingException
中。所有这些例子都是假设的,但你明白了。
最重要的是 - 将原始异常设置为新异常的原因,这样它就不会丢失。
更新:实际上,如果您不能指望客户端合理地从异常中恢复,那么选项5就可以了。更好的是 - 您创建的自定义异常可以扩展RuntimeException
。这就是spring所做的事情,例如,在DataAccessException
中包装所有与数据相关的异常。
答案 1 :(得分:2)
如果你的代码的调用者可以想象处理一些异常,那么我会声明你的方法抛出它们并传递它们。如果没有希望,那么我将创建自己的自定义异常,扩展(取消选中)RuntimeException,并抛出自定义异常,并将实际异常链接到其中。
我一般会推迟决定退出到尽可能高的政策。退出(如果您的意思是退出流程)应始终在代码中推迟,以便您可以对其进行单元测试。
总的来说,我对例外的理念是:
答案 2 :(得分:1)
一般来说,如果你的方法无法处理异常,它应该重新抛出它们或将它们添加到throws部分。隐藏catch块中的异常似乎是最糟糕的选择。
答案 3 :(得分:1)
一如既往,这取决于。
这是你的API吗?如果是,则更改它,让它抛出更少的异常。以某种方式处理它们。
尽量让您的程序尽可能长时间工作。这意味着,如果没有配置文件,请不要抛出IOException并退出。硬编码一些默认配置。如果没有互联网连接,请显示该消息,不要退出。
有时候,可以返回一些特殊的东西(特殊情况模式和空对象模式的变体)而不是抛出异常。
考虑针对某些特殊情况实施Observer模式。不要抛出异常,但要通知应该显示消息或做其他事情的人。
不要隐藏任何一个。记录所有异常。
答案 4 :(得分:1)
如果您的API名为Foo,我会创建一个名为FooAPIException的异常。确保在FooAPIException中嵌入源异常。记录和显示FooAPIException时,还会显示源异常的堆栈跟踪。
例如:
public class FooAPIException extends Exception {
private Exception root;
public FooAPIException (Exception e) {
super(e.getMessage(),e.getErrorCode());
root = e;
}
public Exception getRoot () {
return root;
}
// Exception ================================================================
public String toString () {
StringBuffer sb = new StringBuffer();
sb.append("[");
sb.append(getErrorCode());
sb.append("][");
sb.append(getMessage());
sb.append("]\n");
sb.append("ROOT CAUSE:");
Writer write = new StringWriter();
PrintWriter pw = new PrintWriter(write);
e.printStackTrace(pw);
pw.close();
try {
write.close();
} catch (IOException ioe) {/**/}
root = write.toString();
sb.append(write);
return sb.toString();
}
}
然后包装API:
public class FooAPI {
public static method (String params) throws FooAPIException {
try {
RealFooAPI.method(params)
} catch (Exception e) {
throw new FooAPIException(e);
}
}
}
答案 5 :(得分:0)
您可以使用一些自定义异常包装异常。
然而,问题在于,通过隐藏原因异常(例如,它是IOException
),您隐藏了理论上允许更高级别的代码捕获该异常的信息具体而言,处理它。在这种情况下,你最好不要抛出RuntimeException
,所以你也可以用RuntimeException
包裹它们。
我仍然会留下那些你可以想象的合理的来电者,他们希望专门捕捉并专门宣布,或将它们分组。
答案 6 :(得分:0)
如果您没有处理该方法中的异常,最好将它们包装到一个或多个自定义异常中并抛出它们,以便您可以在较高级别处理它们。
您还可以创建自定义未经检查(扩展的RuntimeException)异常,并将抛出的异常包装到自定义运行时异常中。