简体   繁体   English

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

[英]Invoking overriding method that throws Checked exception

After reading Why can't overriding methods throw exceptions , I understand that if method declared as throws a Checked exception, the overriding method in a subclass can only declare to throw that exception or its subclass: 阅读为什么不能覆盖方法抛出异常 ,我理解如果声明为抛出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
}

So because SocketException IS-A IOException I can declare the overriding method as throws any of subclass of IOException . 因为SocketException IS-A IOException我可以将重写方法声明为抛出IOException任何子类。

In my program, I want to invoke the overriding method declared as throws FileNotFoundException IS-A IOException . 在我的程序中,我想调用声明为抛出的重写方法FileNotFoundException IS-A IOException also handled with a try-catch block 还使用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{}
}

But I am getting that compile-time error: 但我得到编译时错误: 截图

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

What is the reason for that? 这是什么原因? I'm a little confused because everything that the Base class has also available to the subclasses. 我有点困惑,因为Base类也可用于子类。

Also much more confusing is the ability to catch Exception and Throwable In addition to IOException (The opposite from Overriding concept). 除了IOException (与Overriding概念相反)之外,捕获ExceptionThrowable的能力也更令人困惑。

Your object reference is of type Super , even though you know it's a Sub object at runtime. 您的对象引用是Super类型,即使您知道它在运行时是Sub对象。 Therefore the compiler is checking the method definition of the Super and giving you this compile error. 因此,编译器正在检查Super的方法定义并为您提供此编译错误。

It would be no different from getting the following compiler error: 它与获取以下编译器错误没有什么不同:

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

It's important to remember that the throws clause is part of the method definition. 重要的是要记住throws子句是方法定义的一部分。

What is the reason for that? 这是什么原因? I'm a little confused because everything that the Base class has also available to the subclasses. 我有点困惑,因为Base类也可用于子类。

You need to catch an IOException and not a FilenotFoundException . 您需要捕获IOException而不是FilenotFoundException This is because of the fact that while the doStuff method from the subclass will be called at runtime, the compiler doesn't know about this yet. 这是因为虽然子类中的doStuff方法将在运行时调用,但编译器还不知道这一点。 It only knows about the doStuff method in the super class which declares that it throws an IOException . 它只知道超类中的doStuff方法,该方法声明它throws IOException

To address your edit : The catch block can chose to catch the exact exception that is expected in the try block or it can chose to catch a superclass of the exception. 解决编辑问题: catch块可以选择捕获try块中预期的确切异常,也可以选择捕获异常的超类。 The reasoning behind this has got nothing remotely to do with method overriding. 这背后的原因与方法覆盖没有任何关系。

The compiler doesn't consider the type of the object, but the type of reference you are using which is Super . 编译器不考虑对象的类型,而是考虑您使用的引用类型,即Super

As Super.doStuff() throws IOException , this is what you must catch. 由于Super.doStuff() throws IOException ,这是你必须捕获的。

BTW I highly recommend using an IDE, you will find it more productive. 顺便说一下,我强烈建议使用IDE,你会发现它更有效率。

By declaring p as Super 通过声明p为超级

Super p = ...

your Compiler only knows p is some kind of Super . 你的编译器只知道p是某种Super Super 's doStuff() throws an IOException , but your code catches only a special case of IOException , the FileNotFoundException . SuperdoStuff()抛出IOException ,但是你的代码只捕获IOException的特殊情况,即FileNotFoundException If you want to tell your Compiler this is definetly a Sub and not a Super just declare p as Sub . 如果你想告诉你的编译器这肯定是Sub而不是Super只是将p声明为Sub

In this case it's explicit not declared as Sub but as Super so any Super or its Childs might occur and throw any IOException which might not be a FileNotFoundException or any of it's childs. 在这种情况下,它不明确声明为Sub ,但作为Super所以任何Super或其童车可能发生,并抛出任何IOException这可能不是一个FileNotFoundException或任何它的孩子的。

That's because you are using an object of static type Super. 那是因为你使用的是静态类型Super的对象。 The compiler can not know that at runtime p is pointing to a Sub object, so it wants to catch the exceptions thrown by the method declared in the Super class 编译器无法知道在运行时p指向Sub对象,因此它希望捕获由Super类中声明的方法抛出的异常

Because it makes checks by declared type, in this case Super . 因为它按声明的类型进行检查,在这种情况下是Super

It is not known (or checked) that your p will contain only instances of Sub . 不知道(或检查)您的p将仅包含Sub实例。 Also, it would not make sense to define a superclass variable and use it only and only for 1 particular subclass. 此外,定义一个超类变量并仅使用它并且仅用于1个特定子类是没有意义的。

So your Super p contains instance of a Super.class . 所以你的Super p包含一个Super.class实例。 Its method doStuff() can throw everything that extends IOException , lets say UnsupportedEncodingException , but you try-catch only for FileNotFoundException , so that Unsupported... may have been thrown and must be handled. 它的方法doStuff()可以抛出所有扩展IOException东西,比如说UnsupportedEncodingException ,但是你只能尝试捕获FileNotFoundException ,这样就可能抛出了Unsupported...并且必须处理它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM