阅读为什么不能覆盖方法抛出异常,我理解如果声明为抛出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 }
因为SocketException
IS-A IOException
我可以将重写方法声明为抛出任何子类IOException
.
在我的程序中,我想调用声明为抛出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{} }
但我得到编译时错误:
Sub.java:6: error: unreported exception IOException; must be caught or declared to be thrown p.doStuff(); ^
这是什么原因?我有点困惑,因为Base类也可用于子类.
还更令人困惑的是捕捉能力Exception
和Throwable
除IOException
(从重写概念相反).
您的对象引用是类型的Super
,即使您知道它是Sub
运行时的对象.因此,编译器正在检查该方法的定义,Super
并为您提供此编译错误.
它与获取以下编译器错误没有什么不同:
Object o = new String("Hello World"); o.charAt(2); //Obviously not allowed
重要的是要记住该throws
子句是方法定义的一部分.
这是什么原因?我有点困惑,因为Base类也可用于子类.
你需要抓住一个IOException
而不是一个FilenotFoundException
.这是因为虽然doStuff
子类中的方法将在运行时调用,但编译器还不知道这一点.它只知道doStuff
超类中声明它throws
的方法IOException
.
要解决您的编辑问题:catch
块可以选择捕获try
块中预期的确切异常,也可以选择捕获异常的超类.这背后的原因与方法覆盖没有任何关系.
编译器不考虑对象的类型,而是考虑您正在使用的引用类型Super
.
因为Super.doStuff() throws IOException
,这是你必须抓住的.
顺便说一句,我强烈建议使用IDE,你会发现它更有效率.