假设您正在为异步运行的对象编写库。要通知调用者异步对象的状态,调用者必须实现侦听器接口。
现在,在使用侦听器时,侦听器可能会做错,这会导致在库对象中抛出异常。
实施例
public interface SomeListener {
public void progressNotification(int status);
}
public class SomeClass {
SomeListener listener = null;
…
public void setListener(SomeListener listener) {
this.listener = listener;
}
…
public void someRandomMethod() {
int progressStatus = 0;
//Do some stuff here that updates progressStatus
//then notify the caller
if (listener != null) {
listener.progressNotification(progressStatus);
}
}
}
public class CallerClass implements SomeListener{
public void progressNotification(int status) {
//do something that will throw an exception
//e.g assume status is 0
int x = 200/status; //this will throw an ArithmeticException because of division by zero
}
}
如果SomeClass
没有捕获异常并处理它,这将导致listener.progressNotification(progressStatus);
之后的任何代码不被执行而使对象处于“不正确”状态。
所以我的问题是,在库中处理这种异常的最佳方法是什么?
我见过一个这样做的图书馆:
if (listener != null) {
try {
listener.progressNotification(progressStatus);
}catch (Thrwowable th) {
System.err.println("An uncaught throwable " + th);
}
}
对我来说不合适。
答案 0 :(得分:7)
对我而言,听众的合约应该明确界定:
如果它确实抛出了运行时异常,那么监听器就会破坏API契约,因此它就是API客户端代码的错误,而不是API本身的错误。
除了明确定义和记录合同以及解释违约的潜在影响(即不确定状态,无论如何)之外,我不会做任何其他事情。如果客户端真的想要保护自己免受编程错误的影响,他仍然可以将所有侦听器代码包装在try / catch中,如示例所示。
答案 1 :(得分:2)
对所有人来说都是一样的,我们无法为RuntimeException
做任何事情。这就是为什么它们被标记为未经检查的异常。关于未经检查的异常,Here是一个很好的读物。
它清楚地指明了这一点:
运行时异常可以发生在程序的任何地方,而在典型的程序中,它们可能非常多。 必须在每个方法声明中添加运行时异常会降低程序的清晰度。因此,编译器不要求您捕获或指定运行时异常(尽管您可以)。
所以,不用担心它。
但很明显,如果有任何情况可能有任何Checked
例外,则需要妥善处理。
此外,记录可能由方法引发的可能异常是一种很好的做法。
答案 2 :(得分:1)
如果您不希望行为不正常的侦听器停止所有人的所有通知,那么您需要执行这种异常处理。我确实有一些挑剔。当然,我会记录它而不是写入stderr。捕捉Throwable并不是很好,有一些事情(内存错误,一方面)你可能会放手一提。但基本想法还可以。