Java异常包装:糟糕的做法?

num*_*web 7 java exception-handling software-quality exception

来自PHP世界,只有一种方法可以编写异常处理..我发现Java中的异常包装有点"丑陋":

public void exampleOneException(String input) throws MyBusinessException {
    try {
        // do something
    } catch (NumberFormatException e) {
        throw new MyBusinessException("Error...", e);
    }
}
Run Code Online (Sandbox Code Playgroud)

我更喜欢使用这种风格:

public void exampleTwoException() {
    try {
        // do something
    } catch (MyBusinessException e) {
        log.error("Error...: " + e);
    } catch (NumberFormatException e) {
        log.error("Error...: " + e);
    }
}
Run Code Online (Sandbox Code Playgroud)

这些处理例外的方法有什么不同或最佳做法吗?

Mur*_*nik 7

这些都是两种不同场景的有效方法.

在第一种情况下,该方法无法对异常做任何智能,但必须向上"报告"它.这样调用者就可以捕获异常并决定如何处理异常(例如取消流程,向用户弹出消息,记录消息等)

在第二种情况下,您捕获异常并将其记录下来,从而有效地将错误从调用方隐藏起来.如果调用者并不真正关心操作是否成功,则此类处理可能很有用.

  • 如果您确定操作将成功,您也可以不写入catch子句.它被认为是糟糕的编程,但却被广泛使用仅仅是因为人们懒惰^^ (2认同)

pto*_*mli 5

第一个例子通常被认为是更好的方法。

您也不应该认为 是MyBusinessException对 的包装NumberFormatException而应该认为NumberFormatException是的原因MyBusinessException

异常应该适合所公开的接口。接口的调用者不需要了解或处理实现细节。除非NumberFormatException在调用 时真正有意义作为一种错误类型exampleOneException,否则应将其转换为更合适的异常。

更具体的示例通常包括不同的实现,其中不应要求接口的用户处理实现细节(甚至在编译时可能不知道)。

interface MyRepository {
    Object read(int id) throws ObjectNotFoundException;
}

// a sql backed repository
class JdbcRepository implements MyRepository {
    public Object read(int id) throws ObjectNotFoundException {
        try { ... }
        catch (SQLException ex) {
            throw new ObjectNotFoundException(ex);
        }
    }
 }

// a file backed repository
class FileRepository implements MyRepository {
    public Object read(int id) throws ObjectNotFoundException {
        try { ... }
        catch (FileNotFoundException ex) {
            throw new ObjectNotFoundException(ex)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

由于接口声明了它可以返回的错误类型,因此该接口的客户端可以是一致且合理的。添加代码来处理FileNotFoundExceptionSQLException然后实际的实现可能是其中之一,也可能不是,这并不美妙。

考虑在实现中是否有多个地方FileRepository可能抛出异常FileNotFoundException。这是否意味着它们中的每一个都意味着未找到对象

在考虑选项二时exampleTwoException,重要的是要认识到您的catch块实际上表明发生的任何错误的影响都已减轻。在某些情况下,检查的异常会被合理地忽略,但更有可能的是,一个简单的异常

try { ... }
catch (SomeException ex) {
    log.error("caught some exception", ex);
}
Run Code Online (Sandbox Code Playgroud)

实际上是开发人员没有考虑异常后果的结果,或者代码应该包含FIXME.

当你看到这一点时,更是如此catch (Exception ex),或者说,不合情理catch (Throwable ex)

最后,您是否愿意深入研究应用程序,找到需要添加(但)另一个 catch 块来处理新实现的所有位置?也许这就是一个原因catch (Exception ex)...

始终抛出适合抽象的异常