Java 调用引发选中异常的重写方法

Java 调用引发选中异常的重写方法,java,exception-handling,overriding,Java,Exception Handling,Overriding,阅读后,我了解到,如果声明为的方法引发选中的异常,则子类中的重写方法只能声明引发该异常或其子类: class A { public void foo() throws IOException {..} } class B extends A { @Override public void foo() throws SocketException {..} // allowed @Override public void foo() throws SQLExcep

阅读后,我了解到,如果声明为的方法引发选中的异常,则子类中的重写方法只能声明引发该异常或其子类:

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
}
因此,因为
SocketException
IS-A
IOException
我可以将重写方法声明为抛出
IOException
的任何子类

在我的程序中,我想调用声明为throws
FileNotFoundException
IS-A
IOException
的重写方法。还使用try-catch块进行处理

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{}
}
但我得到了编译时错误:

原因是什么?我有点困惑,因为基类的所有内容也都可用于子类


除了
IOException
(与覆盖概念相反)之外,捕获
Exception
Throwable
的功能也更令人困惑。

这是因为您使用的是静态类型的Super对象。
编译器无法知道在运行时p指向子对象,因此它希望捕获由超类中声明的方法引发的异常

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

这与获得以下编译器错误没有区别:

Object o = new String("Hello World");
o.charAt(2); //Obviously not allowed
请务必记住,
throws
子句是方法定义的一部分

原因是什么?我有点困惑,因为基类的所有内容也都可用于子类

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


要解决编辑问题:
catch
块可以选择捕获
try
块中预期的确切异常,也可以选择捕获异常的超类。这背后的原因与方法重写无关

因为它按声明的类型进行检查,在本例中是
Super

不知道(或检查)您的
p
仅包含
Sub
的实例。而且,定义一个超类变量并仅对一个特定的子类使用它是没有意义的


因此,您的
Super p
包含
Super.class
的实例。它的方法<代码> doSuffes()/代码>可以抛出扩展的代码< >代码> IOExux,让我们说<代码> unSudioDeNoCudIdgule,但是您只尝试捕获<代码> FieloToFunDestExpOp> <代码>,以便<代码>未支持…< />代码>可能已经被抛出并必须处理。< / P> < P>编译器不考虑对象的类型,但是您使用的引用类型是
Super

由于
Super.doStuff()抛出IOException
,这是您必须捕获的


顺便说一句,我强烈建议您使用IDE,您会发现它更高效。

将p声明为超级

Super p = ...
您的编译器只知道
p
是某种
Super
Super
doStuff()
抛出一个
IOException
,但您的代码只捕获
IOException
的一个特例,即
FileNotFoundException
。如果你想告诉你的编译器这确实是一个
Sub
而不是一个
Super
,只需将
p
声明为
Sub


在这种情况下,它不是显式地声明为
Sub
,而是声明为
Super
,因此任何
Super
或其子对象都可能出现,并抛出任何
IOException
,这可能不是
FileNotFoundException
或其子对象。

有些人可能会阻止图像。您还可以复制粘贴问题中的编译错误吗。@CKK现在添加了只需更改
Super p=new Sub()
Sub p=new Sub()
但是,java.lang.Object没有
charAt
方法,而
Super
Sub
都同意。然而,原理是完全相同的,编译器只检查您调用的方法是否在引用类型上(
Object
在我的示例中,在您的示例中,
Super
)。除了
IOException
之外,我怎么还可以使用
Exception
Throwable
?这与只能声明抛出该异常或其异常的重写相反subclass@Pau重写的方法无法抛出这些,但您可以捕获它们
Super p = ...