Java:抛出异常而不是特定异常的原因是什么?

时间:2012-09-07 15:25:02

标签: java design-patterns exception-handling

您是否有理由这样做:

void foo() throws Exception
{
    // Do something potentially exceptional
}

而不是抛出现有的或自定义的异常?

10 个答案:

答案 0 :(得分:5)

我可以想到两个案例 - 我能想到的第一个类似案例是在实施finalize()时,你必须抛出Throwable

@Override
protected void finalize() throws Throwable {
    super.finalize();
}

......但是请记住,有人认为应该不鼓励使用finalize。

潜在的第二种情况是使用(编写得很糟)的库,其方法可能抛出Exception,在这种情况下,如果您不想在该特定方法中处理它,您唯一的选择是把它扔到堆栈。

就个人而言,如果那是我,我很可能会在RuntimeException中把它包装起来然后在那里:

public void doSomething() {
    try {
        int x = libraryThing.badMethod(); //Library method that throws "Exception"
    }
    catch(Exception ex) {
        throw new RuntimeException("Couldn't do something", ex);
    }
}

RuntimeException的构造函数的第二个参数在这种情况下很重要,因为如果抛出它会将堆栈跟踪上的原始异常保留为(“由...引起”)。当然,如果你能找到一个更具体的RuntimeException子类,你可以保证它在那个上下文中是相关的(例如IllegalArgumentException),那么使用它会更好。

然而,就普通代码而言,没有 - 我认为它几乎总是一种反模式(通常只是因为懒惰造成的!)

作为一个侧面点,抛出一个RuntimeException并不是那么糟糕 - 它仍然非常不明确,但至少不会强迫调用者明确地捕获所有内容。

答案 1 :(得分:3)

我不会这样做。它提供了有关所发生事件的最少信息。

我认为目前的最佳做法是选择未经检查的异常(这是C#方式)。 foo()方法将捕获已检查的异常并将它们包装在RuntimeException中。

我要么拼出异常,将它们包装在更具体业务的自定义异常中,要么包装RuntimeException。

答案 2 :(得分:3)

它允许该方法抛出任意异常。

这可以在框架上下文中找到,其中任意代码在具有已知签名的方法中运行。在这种情况下它是否“好”......呃。我宁愿看到特定于框架或运行时的异常。

除此之外,它通常是反模式,IMO。

答案 3 :(得分:3)

我经常在我的测试方法中这样做。

@Test
public void testSOmething() throws Exception {

这是我的单元测试的标准签名,它没有专门测试是否抛出异常(这是大多数测试。)

在这些测试之外,我不关心我的测试可能会抛出什么异常,因为在这些情况下抛出异常表示测试方法失败。

我从不在生产代码中这样做。

答案 4 :(得分:2)

如果实际列表很长且没有意义,您可以声明throws Exception。例如当通过反射调用方法时,这可能会导致相当多的异常。

答案 5 :(得分:2)

您可能正在实现Java自己的Callable界面!这总结了一下。如果你提供一些其他人的代码可以运行的上层结构,但你不想限制它们被强制捕获内部的任何和所有已检查的异常。有人可以断言,这对你自己的图书馆本身来说并不坏,但是首先是设置了一个糟糕的Checked Exceptions设计的危险(但那时我们将进行圣战,而不是SO问题。)< / p>

答案 6 :(得分:1)

一般来说,这意味着代码设计不好或底层库设计不好。如果您发现自己没有充分理由声明“抛出异常” - 请考虑抛出RuntimeException。特别是在图书馆代码中。

答案 7 :(得分:0)

通常我发现“throws Exception”对于在其他人实现的接口中声明的方法是可接受的,并且可以有非常不同的实现(你不希望在他们可能抛出的内容中限制可能的实现)。 / p>

当从方法中抛出很多异常时,我发现它也是可以接受的。

我不认为这是一种反模式,而是一种常用于懒惰的习语。

答案 8 :(得分:0)

根据业务规则定义您自己的异常

public void doSomething() {
    try {
        int x = 10/0; //Library method that throws "Exception"
    }
    catch(Exception ex) {
        throw new Exception("this doesn;t work.there is exception", ex);
    }
}

这会覆盖异常方法;

class Exception
{
   Exception()
   {
   }

   Exception(String msg)
   {
      this.msg=msg;      
   }
}

答案 9 :(得分:0)

它通常在测试/快速和肮脏的代码中完成,这是非常合理的。

throws列表冗长乏味 - 半合理

时,有时会这样做

有些开发人员/项目会为所有事情做这件事,因为他们对“已检查”异常有不同的理念,如果他们不打算进行重要的代码共享,那么就可以了(我自己对这个主题有两个想法)与“世界其他地方”。