调用抛出Checked异常的重写方法

时间:2017-01-24 11:20:27

标签: java exception-handling method-overriding

在阅读Why can't overriding methods throw exceptions之后,我理解如果声明为抛出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的任何子类。

在我的程序中,我想调用声明为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{}
}

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

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

这是什么原因?我有点困惑,因为Base类也可用于子类。

除了Exception(与Overriding概念相反)之外,捕捉ThrowableIOException的能力也更加令人困惑。

6 个答案:

答案 0 :(得分:14)

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

与获取以下编译器错误没有什么不同:

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

重要的是要记住throws子句是方法定义的一部分。

答案 1 :(得分:11)

  

这是什么原因?我有点困惑,因为Base类也可用于子类。

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

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

答案 2 :(得分:5)

编译器不考虑对象的类型,但是您使用的引用类型为Super

作为Super.doStuff() throws IOException,这是你必须抓住的。

BTW我强烈建议您使用IDE,您会发现它的效率更高。

答案 3 :(得分:3)

将p声明为超级

Super p = ...

您的编译器只知道p是某种SuperSuper doStuff()引发了IOException,但您的代码只捕获了IOException FileNotFoundException的特例。如果您想告诉您的编译器,这肯定是Sub而不是Super,只需将p声明为Sub即可。

在这种情况下,它显式未声明为Sub,而是Super,因此可能会发生任何Super或其子项并抛出任何可能不会IOException FileNotFoundExceptionSELECT COUNT(*) As 'Deployed', DATENAME(YEAR, LastModified) As 'Year', DATEPART(Month, LastModified), DATENAME(Month, LastModified) As 'Month' FROM [InventoryDatabase].[dbo].[Hardware_RefreshList] WHERE Asset_Type = 'Laptop' AND Status = 'Completed' AND Department != 'SNBc' AND DATENAME(YEAR, LastModified) = '2017' GROUP BY DATEPART(Month, LastModified), DATENAME(YEAR, LastModified), Month(LastModified), DATENAME(Month, LastModified), DATEADD(MONTH, DATEDIFF(MONTH, 0, LastModified), 0) ORDER BY DATEPART(Month, LastModified) 或其中任何一个孩子。

答案 4 :(得分:2)

那是因为你使用的是静态类型Super的对象。 编译器无法知道在运行时p指向Sub对象,因此它想要捕获由超类中声明的方法抛出的异常

答案 5 :(得分:2)

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

我们p仅包含Sub的实例,但未知(或已检查)。此外,定义一个超类变量并仅使用它并且仅用于1个特定子类是没有意义的。

因此,您的Super p包含Super.class的实例。它的方法doStuff()可以抛出所有扩展IOException的内容,比如说UnsupportedEncodingException,但是你只能抓住FileNotFoundException,这样Unsupported...可能会被抛出必须处理。