不同的方式如何抛出多个异常

时间:2014-10-08 09:06:52

标签: java exception exception-handling

当你需要抛出多个例外情况时,我对最佳实践感到困惑。

假设我们已声明异常,如下所示。

public class DaoException extends Exception

public class ClientNotFoundException extends DaoException

public class NotUniqueResultException extends DaoException

现在我们有一个方法,它可以抛出ClientNotFoundExceptionNotUniqueResultException。什么更适合throws条款?

getClientByNumber(Long number) 
    throws ClientNotFoundException, NotUniqueResultException

getClientByNumber(Long number) throws DaoException

您如何在代码中解决这种情况?您是否在应用程序中创建了自己的异常层次结构?

还有其他可能的解决办法吗?

3 个答案:

答案 0 :(得分:4)

我个人认为,对于方法进行某些活动时可能发生的所有可能情况,您应尽可能具有描述性,即我建议:

getClientByNumber(Long number) 
    throws ClientNotFoundException, NotUniqueResultException

原因是调用该方法的那个必须处理您的方法抛出异常的两种情况。您的方法可能会在不同的情况下抛出异常,并且捕获异常的方式可能会有所不同,具体取决于异常的类型。例如:

public void myMethod() {
    try {
        getClientByNumber(1);
    } catch (NotUniqueResultException e) {
        //something that deals with the exception of that specific type.
    } catch (ClientNotFoundException e) {
        //something else that deals with the exception of that specific type.
    }
}

答案 1 :(得分:3)

根据我的经验,通常最好是具体的;从而选择throws ClientNotFoundException, NotUniqueResultException解决方案。这样,用户可以更清楚地看到可以抛出异常以及它们的含义使得处理它们变得更加容易。

如果相关的例外实际上是相关的,那么为您的应用程序创建例外层次结构可能是一个好主意。但是在许多情况下,这不是必需的;例如,NotUniqueResultException可以扩展IllegalStateException(就像我所看到的那样,非法国家)。

答案 2 :(得分:0)

宣布您希望抛出的每种类型的异常都是一个好主意,即使那些是运行时异常的异常。

其中一个原因是Javadoc。想象一下,你有类似的东西。

public void foo( String bar ) throws NullPointerException, IllegalArgumentException {
  if (bar == null) {
     throw new NullPointerException( "bar must not be null" );
  }
  if (bar.equals( "123" ) {
     throw new IllegalArgumentException ( "bar must not have valu 123" );
  }
  ...
}

在您的Javadoc中,您可以准确记录何时抛出的内容。这对您的代码用户来说非常有用,即使他们不想以不同的方式处理它们。 (当然,您可以手动将@throws标记添加到Javadoc,但最好提示。)

在Java 7之前,在一个catch中处理许多异常非常复杂,这诱使开发人员简化他们的throws条款,但是没有理由再这样做了。

尝试的多捕获:

try {
    getClientByNumber(Long number);
} catch ( ClientNotFoundException | NotUniqueResultException ex ) {
   ...
}

这消除了重复catch块的需要(甚至更糟糕的是,捕获Exception)。

重新投掷变得轻松

如果由于某种原因你想要捕获每个异常,记录并重新抛出它,你可以这样做:

 public void foo() throws ClientNotFoundException, NotUniqueResultException {
    try {
       getClientByNumber(Long number);
    } catch ( Exception ex ) {
       ...
       throw ex; //the compiler knows that at this point `ex` is either an unchecked exception, or one of the two declared checked exceptions, therefore this re-throw is valid
    }
 }