4

您是否有理由要这样做:

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

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

4

10 回答 10

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很重要,因为如果抛出它,则会将堆栈跟踪上的原始异常保留为 ("Caused by: x")。当然,如果你能找到一个更具体的 RuntimeException 子类,你可以保证它在那个上下文中是相关的(IllegalArgumentException例如),那么使用它会更好。

然而,就普通代码而言,不——我认为它几乎总是一种反模式(通常是由于懒惰引起的!)

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

于 2012-09-07T15:28:17.550 回答
3

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

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

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

于 2012-09-07T15:28:19.983 回答
3

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

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

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

于 2012-09-07T15:30:03.833 回答
3

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

@Test
public void testSOmething() throws Exception {

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

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

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

于 2012-09-07T15:31:49.423 回答
2

您可以声明throws Exception实际列表是否很长且不有趣。例如,当通过反射调用方法时,这可能会导致很多异常。

于 2012-09-07T15:29:29.000 回答
2

您可能正在实现 Java 自己的Callable接口!大概就是这样总结。如果您提供了一些上层结构,其他人的代码可以在其中运行,但您不想限制他们被迫捕获内部的任何和所有检查异常。有人可以断言,这不是您自己的库本身的糟糕设计,而是首先检查受检异常的糟糕设计的危险(但我们将有一场圣战,而不是一个 SO 问题。)

于 2012-09-07T15:34:45.840 回答
1

通常,这意味着代码设计不佳或底层库设计不佳。如果您发现自己无缘无故地声明“抛出异常” - 请考虑改为抛出 RuntimeException。特别是在库代码中。

于 2012-09-07T15:28:08.353 回答
0

一般来说,我发现“抛出异常”对于在接口中声明的方法是可以接受的,这些方法将由其他人实现并且可以有非常不同的实现(你不想限制它们可能抛出的可能实现)。

当一个方法抛出大量异常时,我发现它也是可以接受的。

我不会认为它是一种反模式,而是出于懒惰而经常使用的成语。

于 2012-09-07T16:01:59.107 回答
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);
    }
}

这会覆盖 Exception 方法;

class Exception
{
   Exception()
   {
   }

   Exception(String msg)
   {
      this.msg=msg;      
   }
}
于 2012-09-07T16:48:01.660 回答
0

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

有时会在throws列表冗长乏味时完成 - 半合理

一些开发人员/项目对所有事情都这样做,因为他们对“已检查”异常有不同的理念,如果他们不打算与“世界其他地区”。

于 2012-09-07T16:58:50.220 回答