Is it okay to declare a checked exception for an exception thrown by a called method?

时间:2017-08-30 08:34:49

标签: java

Consider this:

public void Do() throws Exception {

 if (blah) throw new Exception(...);

 Thingy thingy = ...;

 Foo(thingy);
}

public void Foo(Thingy thingy) throws EmptyThingyException {

   if (thingy == null || 
     thingy.isEmpty()) throw new EmptyThingyException();

  ...
}

public class EmptyThingyException extends Throwable { ... }

In this case, is it okay to not handle EmptyThingyException inside Do and declare Do like so:

public void Do() throws Exception, EmptyThingyException {

or do I have to handle EmptyThingyException inside Do and throw it back again like so:

public void Do() throws Exception, EmptyThingyException {
    try {
    } catch (EmptyThingyException empty) {
      throw empty;
    }
    ...
  }

3 个答案:

答案 0 :(得分:1)

问题的简短回答是:

是的,声明被调用方法抛出的已检查异常是正确的。

方法如何实现其目的是一个实现细节,界面对于它直接做多少或者多少委托给方法都不重要。关于已检查异常的语言规则是经过仔细定义的,以确保方法通告它们可能抛出的所有已检查异常或它们调用的方法(但不由方法本身处理)。让一个未经处理的例外通过'一种方法是事物应该如何运作。 实际上答案是以构造的名义"非本地异常处理"当唯一真正的行动是"没有工作时,它被设想为从无休止的错误处理中一直努力。在接近开始的某个时刻。

要与该方法保持一致,您应该catch例外,您将要做些什么。 应该使用finally来清理代码,因此catch异常的正常原因是在某个时刻记录它和/或放弃任务而不是让堆栈进一步展开。

在这种特定情况下,最好的答案是抛出IllegalArgumentException

throw new IllegalArgumentException("thingy==null || thingy.isEmpty()");

那是不加控制的,明智的。正确的代码不应该遇到非法的参数,并且它们应该很少被抛出并指示程序缺陷(无论是在类,它的包或消费者代码中)。外部和用户输入应该直接验证,程序不应该依赖IllegalArgumentException

在实践中,IllegalArgumentExceptionIllegalStateException应涵盖内部错误'意思是"你不能用那个"或者"你现在不能这样做"分别应该注释以指定故障。

由于消费者代码可能会对可能采取的不同非法行为做出不同反应,因此您可能会对这两者进行分类,这一想法很简单。

程序正确性包括程序从不对程序的某些其他部分进行非法调用或进入无效或损坏的状态,并且只有因环境故障而导致异常才会导致程序中的程序或子任务无法执行按预期完成。

答案 1 :(得分:0)

如果你想要在异常发生后做某事,那么使用try-catch,或者你可以在方法上声明它。

除此之外,如果EmptyThingyException为<{1}}的子类,那么当您声明Exception时,无需声明EmptyThingyException

答案 2 :(得分:0)

1-声明您的方法可以抛出的特定已检查异常

catch (NoSuchMethodException e) {
   throw e; //Avoid this as it doesn't help anything
}

始终避免在上面的代码示例中执行此操作。它完全违背了检查异常的全部目的。声明您的方法可以抛出的特定已检查异常。如果有太多这样的已检查异常,您应该将它们包装在您自己的异常中,并在异常消息中添加信息。如果可能,您也可以考虑代码重构。

2-始终只捕获您可以实际处理的异常

public void Do() throws BlahIsFoundException{
 try {
     if (blah) throw new BlahIsFoundException(...);

     Thingy thingy = ...;

     Foo(thingy);
 } catch(EmptyThingyException exception) {
     //Handle the exception correctly, at least log it
 } finally {
     //Do some clean up if needed, for example close a database connection or free some resources.
 }
}

public void Foo(Thingy thingy) throws EmptyThingyException {

   if (thingy == null || 
     thingy.isEmpty()) throw new EmptyThingyException();

  ...
}

public class EmptyThingyException extends Exception { ... }
public class BlahIsFoundException extends Exception { ... }

这是最重要的概念。不要为了抓住它而抓住任何例外。仅在您要处理它时才捕获任何异常,或者您希望在该异常中提供其他上下文信息。如果你无法在catch块中处理它,那么最好的建议就是不要只是重新抛出它。

3-避免使用Throwable类

Throwable是异常和错误的超类,据我所知你需要在处理异常和错误时使用Throwable,但这绝对不是你的关注,大多数java代码都处理异常和只要您需要处理已检查的异常http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html,就可以了。

** 好吧,如果我是你,我会做类似的事情:

{{1}}

希望有所帮助,这里有一些好的文件可供阅读: http://docs.oracle.com/javase/tutorial/essential/exceptions/index.html http://howtodoinjava.com/best-practices/java-exception-handling-best-practices