通常,在实现模板方法或接口方法时,您只能抛出该方法定义的一种特定类型的异常。但是您的实现可能会为引发不兼容异常类型或许多不同异常类型的 API 生成类。
当然,您需要捕获它们并将异常包装到适合已实现方法签名的类型中。假设我们要实现这个接口:
public interface SomeDataGetter {
public long getSomeData() throws IOException;
}
我们的实现使用了一些其他的 API 产品来实现这一点,我们调用的 API 方法可能有这个签名:
public long loadFromDBOrCache(Object ... params) throws SQLException, IOException, ObjectNotFoundException, RuntimeException, FridayException, NotWeekendException, NumberIs42Exception;
我编造这个是为了演示您无法按具体类型准确枚举所有可能抛出的异常的情况。请注意 IOException 是我们允许的类型从实现中抛出的类型。
现在我可以在实现这个时走懒惰的路线并包装任何适合我的签名的东西:
@Override
public long getSomeData() throws IOException {
try {
return loadFromDB(...);
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
这显然会将任何异常包装到 IOException(甚至是 IOException)中,并且运行正常。但我不想包装IOExceptions,因为我可以在不包装它们的情况下抛出它们:
@Override
public long getSomeData() throws IOException {
try {
return loadFromDB(...);
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException(e.getMessage(), e);
}
}
您可以想象,如果实现中存在多个可能的异常并且您在实现中允许出现多个异常,那么这很快就会变得很麻烦。对于我想通过的每个异常,我都需要一个额外的捕获。
什么是保持可读性的最佳习语(另外,我很懒,不想写所有这些额外的捕获)并且仍然避免不必要的异常嵌套?或者我不应该打扰,只是把所有东西都包起来?