2008-10-16 19 views
0

存在这种异常系统的风格,其中组件抛出特定于组件的异常。例如,所有数据访问类别都会抛出DataAccessException从组件中包装异常

在这种风格,我经常发现自己不得不赶上并重新抛出的成分具有特异性异常,因为调用的方法是delcared为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); 
} 

你发现自己做同样的?你觉得它很丑吗?

这个问题不是关于这种风格的有效性,而是这种风格约束之内的东西。

回答

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是只有因果,而不是语义相关的。

如果您需要它们来区分不同的异常(例如,应通过与AccessDeniedException不同的操作更正SQLExecutionException),那么您的方法不适用(因为强制在每个catch中使用getCause()需要做的事情非常糟糕,没有任何好处,而只是在前面捕捉正确的例外)。

如果所有调用类都需要报告错误并取消,那么包装可能没问题,但我不会这样做,因为它没有什么好处,如果以后需要区分会使您重写很多东西。

什么是有用的是创建同一类型的例外hierarchy of exceptions,在该行:

如果DataAccessException的将是根,那么你就可以例如具有DataSourceUnavailableException,InvalidDataSourceException,InvalidDataException然后就可以决定只捕获任一父母(如果行动相同)或分别捕获每个异常。

顺便说一句,你为什么需要这样做?

+0

您所评论的风格:-)请假设我不得不跟进它(曾经在那种情况下?)。 问题是关于实际的第一次捕获。它没有用处,没有它,我们得到一个ComponentException与另一个ComponentException作为原因,这是不期望的。 – 2008-10-16 08:26:24

+0

如何抛出新的ComponentException(“来自foo():”+ foo)的错误结果; 抛出一个带有ComponentException的ComponentException作为原因? – 2008-10-16 08:35:57

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