处理侦听器抛出的java异常

时间:2011-08-26 14:05:26

标签: java exception-handling

假设您正在为异步运行的对象编写库。要通知调用者异步对象的状态,调用者必须实现侦听器接口。

现在,在使用侦听器时,侦听器可能会做错,这会导致在库对象中抛出异常。

实施例

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);
        }
    } 

对我来说不合适。

3 个答案:

答案 0 :(得分:7)

对我而言,听众的合约应该明确界定:

  • 它必须快速返回(即不暂停或睡眠线程等),
  • 它不能抛出任何运行时异常。

如果它确实抛出了运行时异常,那么监听器就会破坏API契约,因此它就是API客户端代码的错误,而不是API本身的错误。

除了明确定义和记录合同以及解释违约的潜在影响(即不确定状态,无论如何)之外,我不会做任何其他事情。如果客户端真的想要保护自己免受编程错误的影响,他仍然可以将所有侦听器代码包装在try / catch中,如示例所示。

答案 1 :(得分:2)

对所有人来说都是一样的,我们无法为RuntimeException做任何事情。这就是为什么它们被标记为未经检查的异常。关于未经检查的异常,Here是一个很好的读物。

它清楚地指明了这一点:

  

运行时异常可以发生在程序的任何地方,而在典型的程序中,它们可能非常多。 必须在每个方法声明中添加运行时异常会降低程序的清晰度。因此,编译器不要求您捕获或指定运行时异常(尽管您可以)。

所以,不用担心它。

但很明显,如果有任何情况可能有任何Checked例外,则需要妥善处理。

此外,记录可能由方法引发的可能异常是一种很好的做法。

答案 2 :(得分:1)

如果您不希望行为不正常的侦听器停止所有人的所有通知,那么您需要执行这种异常处理。我确实有一些挑剔。当然,我会记录它而不是写入stderr。捕捉Throwable并不是很好,有一些事情(内存错误,一方面)你可能会放手一提。但基本想法还可以。