请考虑以下代码:
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;
答案 0 :(得分:1)
继承可让您使功能更具体。
你可以减少你抛出的东西,你可以返回一个返回类型的子类型,你可以接受一个参数类型的超类型。
这是因为对您的方法的任何可能调用大多数是对super方法的合法调用,但反过来不一定是真的。
换句话说,在你的例子中:
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,则不允许这样做。
答案 1 :(得分:1)
覆盖时,不能抛出更大或更新的异常。不允许抛出超类方法的异常。
重写方法不得抛出新的或更广泛的已检查异常,而不是被重写方法声明的异常。例如,声明FileNotFoundException的方法不能被声明SQLException,Exception或任何其他非运行时异常的方法覆盖,除非它是FileNotFoundException的子类。