【问题标题】:Why can I declare a function without the "throws" keyword?为什么我可以声明一个没有“throws”关键字的函数?
【发布时间】:2014-07-03 13:42:38
【问题描述】:

考虑以下代码:

public interface I1 {
 public void bar1() throws IOException; 
} 

public interface I2 extends I1 { 
 public void bar2() throws Exception; 
} 

public interface I3 { 
 public void bar3() throws Exception; 
} 

public abstract class A implements I2 { 
 public void bar2() throws Exception{}; 
 public void bar3() throws Exception{}; 
 protected abstract void bar4(); 
 protected void bar5() {}; 
}

现在,我创建了一个类,B,如下所示:

public class B extends A implements I3 {

    @Override
    protected void bar4() {}

    public void bar1()  {}

}

为什么编译器让我这样做?我的意思是,不应该是:
public void bar1() throws IOException;

【问题讨论】:

  • 你可以这样想:I1 告诉我们可能发生的最坏情况是什么,因为每个人都接受一个实现 I1 的类需要为最坏的情况做好准备。现在你实现了bar1(),但它实际上并没有抛出IOException。可能发生的最坏情况是什么?与抛出IOException 相比,该实现显然没有那么糟糕。如果其他一些类使用实现I1 的类,它不会改变任何东西。该实现已准备好处理IOExceptions,但它们永远不会发生。

标签: java oop exception inheritance interface


【解决方案1】:

重写时,您不能抛出更广泛或更新的异常。允许不抛出超类方法的异常。

覆盖方法不得抛出比被覆盖方法声明的新异常或更广泛的已检查异常。例如,声明 FileNotFoundException 的方法不能被声明 SQLException、Exception 或任何其他非运行时异常的方法覆盖,除非它是 FileNotFoundException 的子类。

【讨论】:

  • 为什么public void bar1() throws NullPointerException {} 有效?它不是IOException 的子类。
  • NullPointerException 不是检查异常。所以,即使这样也没关系。覆盖时,只有 CHECKED 异常被限制为更窄或更小的异常。 IOException 是检查异常,因此应用了规则。
【解决方案2】:

继承使您可以使函数更具体。

你可以减少你抛出的东西的数量,你可以返回一个返回类型的子类型,你可以接受一个参数类型的超类型。

这是因为对您的方法的任何可能调用大部分都是对超级方法的合法调用,但反过来不一定是正确的。

换句话说,在你的例子中:

new B().bar1() 

你知道它不会抛出异常,你不需要捕获。

((A)new B()).bar1()

您需要捕获异常,因为您现在正在处理任何 A 或 A 的子类,您可能需要处理它。

如果您尝试反过来创建一个 C 类:

public class C extends A implements I3 {

    @Override
    protected void bar4() {}

    public void bar1() throws IOException, SomeOtherException {}

}

现在不允许这样做,因为如果您尝试将 C 用作 A,您将不会捕获 SomeOtherException。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-03-19
    • 2018-07-07
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多