【问题标题】:Declare-and-throw vs. throw-without-being-declared exceptions声明并抛出与未声明异常的抛出
【发布时间】:2008-11-21 18:57:55
【问题描述】:

在Java中,孪生方法有什么区别?

public void methodA() throws AnException {
    //do something
    throw new AnException();
}

public void methodA() {
    //do the same thing
    throw new AnException();
}

我有一种直觉,它与设计良好的方法有关(因为我将 methodA 放在接口中,以 methodA* 在其实现中的方式声明它,并收到来自 Java 的警告“A* 不能覆盖 A,因为 A* 不会抛出 AnException")。

这个猜测正确吗?

这两种做事方式是否还有其他微妙的内涵?

【问题讨论】:

    标签: java exception


    【解决方案1】:

    如果 AnException 是一个检查异常(换句话说,如果它不扩展 RuntimeException),那么 methodA 将不会编译。必须始终声明已检查的异常。

    如果 AnException 是未经检查的异常(如果它确实扩展了 RuntimeException),则 java 编译器允许其中任何一个,并且 java 运行时对任何一个进行等效解释。 出于文档的原因,在这种情况下,方法A 可能仍然是首选。您的方法的 javadoc 将显示它可能会抛出 AnException。最好让您的方法的用户知道他们应该期待什么异常。

    【讨论】:

    • 您似乎将这两个示例都称为“methodA”,这有点令人困惑。
    【解决方案2】:

    除了其他人给出的关于您自己的方法可编译性的好答案之外,还有在超类中实现接口和覆盖方法的问题。

    规则说你可以重写/实现一个方法,但你不能声明额外的例外 那些由原始方法签名声明的。为了理解这一点,想想这个例子。

    假设您正在使用某种数据结构:

    public abstract class AbstractBox {
      public abstract void addItem(Item newItem);
      public abstract void removeItem(Item oldItem);
    }
    

    您有自己的实现,但您决定声明未出现在原始签名中的异常:

    public class MyBox extends AbstractBox {
      public void addItem(Item newItem) throws ItemAlreadyPresentException {...}
      public void removeItem(Item oldItem) throws NoSuchItemException {...}
    }
    

    现在让我们考虑这个处理 Box 对象并接收 MyBox 实例的通用代码:

    public void boxHandler(AbstractBox box) {
      Item item = new Item();
      box.removeItem(item);
    }
    

    编写此代码的人没有预料到任何异常,她也不打算处理实现程序异常。为防止这种情况,编译器将不允许您在原始签名中声明其他异常。

    当然,如果您在内部处理异常...好吧,编译器将非常乐意允许您从签名中删除声明的异常;-)

    希望这会有所帮助...

    尤瓦尔=8-)

    【讨论】:

    • 您不能声明或抛出额外的检查异常。但是,您可以抛出其他未声明的未经检查的异常和错误。
    • 未经检查的异常和错误意味着在没有声明的情况下被抛出,并且表示使用代码没有可行的处理选项并且应用程序应该崩溃的情况。这总是正确的,与覆​​盖方法无关。 =8-)
    【解决方案3】:

    第一个方法必须在 try catch 块中或在声明 throws AnException 的方法中调用 否则编译会失败。

    第二个没有这个限制

    【讨论】:

      【解决方案4】:

      在第二种方法中,AnException 类需要是 RuntimeException 的子类,这意味着声明不是强制性的,方法调用者不必处理它。 RuntimeException 的一个示例是 ArrayOutOfBoundException,想象一下,如果您每次使用 List 时都会显式处理异常(通过声明 throws 或使用 try/catch 块)。

      【讨论】:

        【解决方案5】:

        出于纯粹的文档原因,最好将异常包含在函数定义中。这样,调用者就可以清楚地知道需要处理哪些异常。我也猜测编译器需要为抛出异常的函数做一些高级设置。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-04-20
          • 2013-03-28
          • 1970-01-01
          • 1970-01-01
          • 2015-07-21
          • 1970-01-01
          • 2023-03-05
          • 1970-01-01
          相关资源
          最近更新 更多