调用引发已检验异常的重写方法

2022-09-04 05:53:09

在阅读了为什么不能重写方法抛出异常之后,我了解到,如果声明为Rest checked异常的方法,则子类中的重写方法只能声明抛出该异常或其子类:

class A {
   public void foo() throws IOException {..}
}

class B extends A {
   @Override
   public void foo() throws SocketException {..} // allowed

   @Override
   public void foo() throws SQLException {..} // NOT allowed
}

因此,因为 IS-A,我可以声明重写方法为抛出 的任何子类。SocketExceptionIOExceptionIOException

在我的程序中,我想调用声明为 throw is-A 的重写方法。也使用试捕捉块进行处理FileNotFoundExceptionIOException

import java.io.*;
class Sub extends Super{
    public static void main (String [] args){
        Super p = new Sub();
        try {
            p.doStuff();
        }catch(FileNotFoundException e){

        }
    }
    public void doStuff() throws FileNotFoundException{}
}

class Super{
    public void doStuff() throws IOException{}
}

但是我得到了编译时错误:Screenshot

Sub.java:6: error: unreported exception IOException; must be caught or declared to be thrown
                    p.doStuff();
                             ^

这是什么原因呢?我有点困惑,因为基类的所有内容也可供子类使用。

同样更令人困惑的是捕获和除了的能力(与覆盖概念相反)。ExceptionThrowableIOException


答案 1

您的对象引用类型为 ,即使您在运行时知道它是一个对象。因此,编译器正在检查 的方法定义,并为您提供此编译错误。SuperSubSuper

这与收到以下编译器错误没有什么不同:

Object o = new String("Hello World");
o.charAt(2); //Obviously not allowed

请务必记住,该子句是方法定义的一部分。throws


答案 2

这是什么原因呢?我有点困惑,因为基类的所有内容也可供子类使用。

您需要捕获 一个 而不是 一个 .这是因为虽然子类中的方法将在运行时调用,但编译器还不知道这一点。它只知道超类中声明它是 .IOExceptionFilenotFoundExceptiondoStuffdoStuffthrowsIOException

解决您的编辑问题 :块可以选择捕获块中预期的确切异常,也可以选择捕获异常的超类。这背后的原因与方法覆盖没有任何关系。catchtry


推荐