1

I was practicing exception handling mechanisms with method overriding in java...My code is as follows:

class base {
    void show() {    
        System.out.println("in base class method");    
    }
}

class derived extends base {
    void show() throws IOException {    
        System.out.println("in derived class method");
        throw new IOException();
    }
}

class my {
    public static void main(String[] args) {  
        try {
            base b = new derived();
            b.show();
        }    
        catch (IOException e) {
            System.out.println("exception occurred at :" + e);
        }   
    }
}

Showing an error :

cmd window

So, I corrected following:

void show() throws IOException{

and it is working correctly...

One more experiment I did :

void show() throws Exception{

but it was also showing an error:

cmd window

As I understand, this is because of an overridden method's throws clause should mention the exact checked exception in throws clause of super class method.

As in second case, if I write IOException's superclass Exception in throws clause, it also shows an error. why? Even if Exception is parent class of all exceptions.

I just experimented...what this error tells I don't know...

Can any one please explain what it says and what are the constraints for mentioning checked exception in throws clause of an overridden method?

Community
  • 1
  • 1
Krupal Shah
  • 8,949
  • 11
  • 57
  • 93

2 Answers2

3

There are two related errors in the sample:

1) Your base class method provides the "template" or basic criteria for the derived class method.

So, the base class should declare a super-set i.e. either the same exception class or base exception class of the derived class. You cannot declare that it throws nothing, because then the criteria will not match.

So if your derived class method is like this:

class Derived extends Base {
    void show() throws IOException {
        //...
    }
}

Then base class method "must" be:

class Base {
    void show() throws /*Same or base classes of IOException*/ {
        //...
    }
}

So both of these work:

class Base {
    void show() throws Exception {
        //...
    }
}

or

class Base {
    void show() throws Throwable {
        //...
    }
}

2) When you try the above, the overall declaration of your show method now becomes throws Exception. As a result, anyone who uses this show must catch that exception.

In your main method, you are catching IOException. This will no longer work, the compiler complains "ok you are catching the IOException, what about all the other possibilities from Exception?" This is the second error that you showed.

To fix this, change the main method catch to include Exception as declared in the base class:

class My {
    public static void main(String[] args) {
        try {
            base b = new derived();
            b.show();
        }
        /* NOTE: CHANGED FROM IOException TO Exception */
        catch (Exception e) {
            System.out.println("exception occurred at :" + e);
        }   
    }
}
Krupal Shah
  • 8,949
  • 11
  • 57
  • 93
metacubed
  • 7,031
  • 6
  • 36
  • 65
  • ok..but say me if I declare only Exception in derived, could I declare IOException in super class? – Krupal Shah Aug 09 '14 at 16:06
  • 1
    @krupalshah no, since the base class says "any IOException is allowed" to be thrown. So the derived class can only throw some sort of IOException to match that restriction. – metacubed Aug 09 '14 at 16:08
  • so what is the criteria for declaring checked exception in throws clause of overridden method? – Krupal Shah Aug 09 '14 at 16:12
  • 1
    No, A derived class can only declare same OR child exception OR Runtime exception. – Maas Aug 09 '14 at 16:13
  • @krupalshah like I mentioned in my answer, any "more restrictive" version of the base declaration. So you can use either the same exception or derived classes of the base exception. – metacubed Aug 09 '14 at 16:14
  • @Maas please explain in answer if you know...sometimes comments are skipped. – Krupal Shah Aug 09 '14 at 16:16
  • 1
    I know, if you want to know better follow this simple example. https://code.google.com/p/learn-java/wiki/OverridenMethod – Maas Aug 09 '14 at 16:20
  • @metacubed so, in second case, I exactly tried that as I mentioned in my question...I declared Exception in super class method(which is parent of IOException) and IOException in sub class overridden method...but it is also showing an error...why? – Krupal Shah Aug 09 '14 at 16:21
  • 1
    That is impossible... I will paste you similar code in Answer – Maas Aug 09 '14 at 16:25
  • 1
    @krupalshah that is another error entirely. It is coming from your `main` function catch. Because the base class now throws Exception, you also have to catch Exception, not IOException. – metacubed Aug 09 '14 at 16:26
  • @krupalshah I'm editing my answer to include both situations. – metacubed Aug 09 '14 at 16:29
  • @metacubed thank you..I will appreciate if you explain about this 'another error'..(really horror:-)) – Krupal Shah Aug 09 '14 at 16:31
  • @krupalshah check now.., – metacubed Aug 09 '14 at 16:39
  • @metacubed I will like to accept first then check:-) – Krupal Shah Aug 09 '14 at 16:39
1

Overridden methods may contain only the same checked exceptions in their throws clause as the super-method, or derived types at most.

For example if you say

class Base {

    public void foo(int y) throws IOException {
        // ...
    }
}

and

class Derived extends Base {

    public void foo(int y) throws Exception {
        // ...
    }
}

then your compiler will say that the foo method inside Derived is incompatible with the throws clause in its superclass.

The other way around works because if I say

class Base {

    public void foo(int y) throws Exception {
        // ...
    }
}

and

class Derived extends Base {

    public void foo(int y) throws IOException {
        // ...
    }
}

it's OK.

Why.

Think about the usage of your methods. Java expects you to be using the method polymorphically such as

Base a = new Derived();
a.foo(3);

As such, the compiler will force you to catch the exception thrown by foo in your declared type of the variable (Base). So your code will become

Base a = new Derived();
try {
    a.foo(3);
} catch (Exception e) {
    // ...
}

Therefore, the subtype of Exception you declared in the Derived type is OK with your code above (a catch for an Exception will work for any of its subtypes as well) and as such, Java will allow you to declare IOException in derived, because it will cause no worries later on.

webuster
  • 2,490
  • 18
  • 27