【问题标题】:Why does the caller of the method that throws an exception not have to handle the exception in this situation?为什么抛出异常的方法的调用者在这种情况下不必处理异常?
【发布时间】:2014-12-19 11:52:40
【问题描述】:

考虑如下界面:

package hf;

public interface BadInterface 
{
    void meth() throws Exception;
}

由以下类实现:

package hf;

public class apples implements BadInterface
{
    public static void main(String[] args)
    {
        new apples().meth();
    }

    public void meth()
    {
        System.out.println("Ding dong meth.");
    }
}

虽然 meth() 是一个抛出异常的方法,但方法 meth() 的调用者不必处理或声明异常,程序就可以成功运行。为什么会这样? 是不是违反了每当你调用一个抛出异常的方法时,都需要捕获异常或者声明自己抛出异常的规则?

【问题讨论】:

  • 您应该将您的类重命名为 Apples 以符合 Java 编码规范。

标签: java exception interface exception-handling try-catch


【解决方案1】:

当你实现一个接口方法时,你可以声明你抛出的异常比接口中列出的更少

当您调用new apples().meth() 时,您正在调用apples 实例上的meth()。编译器知道这不会抛出任何东西,所以你很好。

你完成了吗:

BadInterface foo = new apples();  // Note: should be Apples (code style)
foo.meth();

那么你需要捕获接口中声明的异常,因为编译器只知道它正在处理BadInterface 实例。

【讨论】:

  • 还要注意异常不是方法签名的一部分。这就是为什么您无需添加throws Exception 即可实现该方法的原因。您还可以添加例外:public void meth() throws IOException, FooException
  • @Davio 异常肯定与签名相关 - 例如,您不能抛出任何未在界面中列出的已检查异常。
  • 最近,更合适的术语是“形状”,与 lambda 转换相关。声明的异常肯定会影响方法的形状。
  • @Duncan 实际上可以,但前提是异常是接口中抛出的异常的子类。
  • @Davio 也许我们在谈论不同的事情。您当然可以抛出允许的异常的子类。所以在不太可能的情况下,接口有throws Exception,那么可以肯定 - 你可以添加任何东西。这是你的建议吗?
【解决方案2】:

根据JLSRequirements in Overriding and Hiding

B是类或接口,A是B的超类或超接口,B中的方法声明m2覆盖或隐藏A中的方法声明m1。那么:

对于 m2 的 throws 子句中列出的每个检查异常类型, 同一个异常类或其超类型之一必须出现在 删除 m1 的 throws 子句(第 4.6 节);否则,编译时 发生错误。

意味着扩展方法只能有更强的异常策略。如果它具有较弱的限制,则不能使用此类方法代替基本方法,并且会破坏覆盖的概念。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多