简体   繁体   中英

Ovrerriding methods and handling exceptions

I am aware of Liskov Substitution Principle.

But I still have a question about the following code:

Below code has parent class A and subclass B. testException method is overridden in B subclass such that it does not throw any checked exception.

public class A {
    public void testException() throws IOException{
        //some code with IO  
    }
}

public class B extends A {
    public void testException() {
        //no IO code
    }
}

public class Test {

    public static void main(String[] args) {
        first:
        try {// compilation error
            B b = new B();
            b.testException();
        } catch (IOException e) {}

        second:
        try {
            A a = new B();// Why does not cause compilation error?
            a.testException();
        } catch (IOException e) {}

    }

}                 

In Test class, try-catch block labelled first doesn't compile. But second block does without any problems. Why is that?

Update: I think second block is compiling only because of runtime polymorphism, that object a of type A can be pointing to any subclass during runtime, and compiler would not have a clue about it, right?

您的错误是由于您的B类中的testException方法不会引发IO异常而导致的,因此在try / catch块中没有可能捕获的异常。

I think second block is compiling only because of runtime polymorphism, that object a of type A can be pointing to any subclass during runtime, and compiler would not have a clue about it, right?

Yes, that is the case. In first block we are sure that b

B b = ...
b.testException();

is of type of B which means that it can hold instance of class B or its subclass. Since compiler knows that testException() method in class B (or its subclasses) will never throw any IOException (subclasses can't add new checked exceptions to overridden methods) it informs you that you are trying to do something unnecessary (creating dead code - code which will never be executed) which in this case is handling exception which doesn't have chances to be thrown here.

This situation is different in case of second block because there we have

A a = ....
a.testException();

Here compiler can't be sure which object will be held by a (at least not in its current version, maybe in the future this behaviour will be improved). So while it is possible that it will hold instance of class B , it is also possible that it will be instance of class A . So since there is possibility that testException will throw IOException and compilers doesn't see any reason to stop you from handling it (actually handling it is mandatory here because of that posibility).

 A a = new B();
 a.testException();

the compiler will ask for a try-catch block or a throws clause here because polymorphism is a runtime phenomenon , and compiler is resolving the method call at compile time .

so , it sees that testException() in A throws IOException and thus asks for a try-catch block or throws clause.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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