您是否有理由要这样做:
void foo() throws Exception
{
// Do something potentially exceptional
}
而不是抛出现有的或自定义的异常?
您是否有理由要这样做:
void foo() throws Exception
{
// Do something potentially exceptional
}
而不是抛出现有的或自定义的异常?
我可能会想到两种情况——我能想到的第一个类似情况是在实施时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
并不是那么糟糕 - 它仍然非常不具体,但至少不会强制调用者明确地捕获所有内容。
我不会这样做的。它提供了关于所发生事件的最少信息。
我认为当前的最佳做法是更喜欢未经检查的异常(这是 C# 方式)。foo() 方法将捕获已检查的异常并将它们包装在 RuntimeException 中。
我要么拼出异常,将它们包装在更特定于业务的自定义异常中,要么包装 RuntimeException。
它允许该方法抛出任意异常。
这可以在框架上下文中找到,其中任意代码在具有已知签名的方法中运行。在那种情况下它是否“好”......嗯。我宁愿看到特定于框架的或运行时异常。
除此之外,它通常是一种反模式,IMO。
我经常在我的测试方法中这样做。
@Test
public void testSOmething() throws Exception {
这是我的标准签名,用于不专门测试是否抛出异常的单元测试(这是大多数测试。)
在这些测试之外,我不在乎我的测试可能会抛出什么异常,因为在这些情况下抛出异常代表被测方法的失败。
不过,我从不在生产代码中这样做。
您可以声明throws Exception
实际列表是否很长且不有趣。例如,当通过反射调用方法时,这可能会导致很多异常。
您可能正在实现 Java 自己的Callable接口!大概就是这样总结。如果您提供了一些上层结构,其他人的代码可以在其中运行,但您不想限制他们被迫捕获内部的任何和所有检查异常。有人可以断言,这不是您自己的库本身的糟糕设计,而是首先检查受检异常的糟糕设计的危险(但我们将有一场圣战,而不是一个 SO 问题。)
通常,这意味着代码设计不佳或底层库设计不佳。如果您发现自己无缘无故地声明“抛出异常” - 请考虑改为抛出 RuntimeException。特别是在库代码中。
一般来说,我发现“抛出异常”对于在接口中声明的方法是可以接受的,这些方法将由其他人实现并且可以有非常不同的实现(你不想限制它们可能抛出的可能实现)。
当一个方法抛出大量异常时,我发现它也是可以接受的。
我不会认为它是一种反模式,而是出于懒惰而经常使用的成语。
根据业务规则定义您自己的例外
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;
}
}
它通常在测试/快速而肮脏的代码中完成,这是非常合理的。
有时会在throws
列表冗长乏味时完成 - 半合理
一些开发人员/项目对所有事情都这样做,因为他们对“已检查”异常有不同的理念,如果他们不打算与“世界其他地区”。