存在这种异常系统样式,其中组件抛出特定于组件的异常。例如,所有数据访问类都抛出DataAccessException
。
在这种风格中,我经常发现自己必须捕获并重新抛出组件特定的异常,因为被调用的方法被定义为throws Exception
:
try {
int foo = foo();
if (foo != expectedValue) {
throw new ComponentException("bad result from foo(): " + foo);
}
bar();
}
catch (ComponentException e) {
throw e;
}
catch (Exception e) {
throw new ComponentException(e);
}
你发现自己也这样做了吗?你觉得它难看吗?
这个问题不是关于这种风格的有效性,而是在这种风格的约束下。
答案 0 :(得分:3)
这很难看。我想,没有更多的评论这种丑陋的风格了。如果您已经拥有使用原因处理不同问题的所有代码,那就可以了。只是使用
try {
componentCall();
} catch (ComponentException e) {
Throwable t = e.getCause();
//Handle each possible cause
}
比其他方式更难以维护和混淆,重点是我认为使用它没有任何好处。
鉴于您只能使用它,我至少会尝试避免在有和没有原因的情况下抛出ComponentException,这会使它更加困惑,在您的示例中我添加了InvalidFooException并将其添加为通用ComponentException的原因。
try {
int foo = foo();
if (foo != expectedValue) {
throw new InvalidFooException("bad result from foo(): " + foo);
}
bar();
}
catch (Exception e) {
throw new ComponentException(e);
}
getCause()仅供chains of exceptions用于因果关系而非语义相关。
如果您需要它们来区分不同的异常(例如,SQLExecutionException应该通过与AccessDeniedException不同的操作来纠正)那么您的方法不适用(因为强制在每个catch中使用getCause()来查看需要做的很糟糕,并没有提供任何好处,只能在前面捕获正确的异常。)
如果所有调用类都必须报告错误并取消,那么包装可能没问题,但是我不会这样做,因为它增加了很少的好处,如果你以后需要区分将使你重写的东西。
有用的是为同一类型的例外创建一个hierarchy of exceptions,排在:
如果DataAccessException是根,那么你可以例如有DataSourceUnavailableException,InvalidDataSourceException,InvalidDataException然后你可以决定只捕获任一个父项(如果操作是相同的)或单独捕获每个异常。
顺便说一下,为什么你需要这样做呢?
答案 1 :(得分:0)
这样做可能不那么难看(如果函数foo()是声明抛出异常的函数):
int foo;
try {
foo = foo();
}
catch (Exception e) {
throw new ComponentException(e);
}
if (foo != expectedValue) {
throw new ComponentException("bad result from foo(): " + foo);
}
bar();