6

What I have known till now is that a subclass if overriding a superclass method should throw the same exception or a subclass of the exception.

For example:

This is correct

class SuperClass {
    public int doIt(String str, Integer... data)throws ArrayIndexOutOfBoundsException{
 String signature = "(String, Integer[])";
 System.out.println(str + " " + signature);
 return 1;
 }
}

public final class SubClass extends SuperClass {
    public int doIt(String str, Integer... data) throws ArrayIndexOutOfBoundsException {
        String signature = "(String, Integer[])";
        System.out.println("Overridden: " + str + " " + signature);
        return 0;
    }

    public static void main(String... args) {
        SuperClass sb = new SubClass();
        try {
            sb.doIt("hello", 3);
        } catch (Exception e) {
        }
    }
}

This is Incorrect

class SuperClass {
    public int doIt(String str, Integer... data)throws ArrayIndexOutOfBoundsException{
 String signature = "(String, Integer[])";
 System.out.println(str + " " + signature);
 return 1;
 }
}

public final class SubClass extends SuperClass {
    public int doIt(String str, Integer... data) throws Exception {
        String signature = "(String, Integer[])";
        System.out.println("Overridden: " + str + " " + signature);
        return 0;
    }

    public static void main(String... args) {
        SuperClass sb = new SubClass();
        try {
            sb.doIt("hello", 3);
        } catch (Exception e) {
        }
    }
}

But my question is, why this code block is considered correct by compiler?

class SuperClass {
    public int doIt(String str, Integer... data)throws ArrayIndexOutOfBoundsException{
 String signature = "(String, Integer[])";
 System.out.println(str + " " + signature);
 return 1;
 }
}

public final class SubClass extends SuperClass {
    public int doIt(String str, Integer... data) throws RuntimeException {
        String signature = "(String, Integer[])";
        System.out.println("Overridden: " + str + " " + signature);
        return 0;
    }

    public static void main(String... args) {
        SuperClass sb = new SubClass();
        try {
            sb.doIt("hello", 3);
        } catch (Exception e) {
        }
    }
}
Abhinav Sarkar
  • 23,534
  • 11
  • 81
  • 97

4 Answers4

6

This is because in Java every method can throw a RuntimeException (or an Error) at any time. It does not even need to be declared in the throws part of your method signature. So it is possible to also throw a exception which is a super type of the one declared in your overridden method, as long it is still a sub type of RuntimeException.

See Chapter 11 (Exceptions) of the Java Language Specification for the specification for this behavior, especially 11.1.1. The Kinds of Exceptions which defines checked (needs to be specified in throws clause) and unchecked (does not need to be specified in throwsclause) exceptions.

siegi
  • 5,646
  • 2
  • 30
  • 42
2

When you override a method, you should define the same checked exceptions. In this case, the SuperClass#doIt method declares that throws an ArrayIndexOutOfBoundsException, so every children that override that method should declare the same checked exceptions or its subclasses.

More info:

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
  • Does it mean, if a Runtime exception is thrown by the superclass method, any superclass in the exception hierarchy can be thrown. –  Sep 30 '12 at 18:16
  • Exception --> RuntimeException --> IndexOutOfBoundException --> ArrayIndexOutOfBoundException –  Sep 30 '12 at 18:17
  • Yes, that is correct. The exception declared in the override must be in its descendant tree, it can't be bigger than the exception declared in the super class. – Luiggi Mendoza Sep 30 '12 at 18:19
  • 3
    @BugMeNot RuntimeException isn't a checked exception, that's the reason it works. – Joachim Isaksson Sep 30 '12 at 18:19
  • @Luiggi Mendoza,thats correct.But why this rule is enforced by java.I wanted to know the reason behind it? – Nirdesh Sharma Jun 03 '13 at 06:29
1

To make an attempt to make it simple, RuntimeException and Error don't need to be declared in throws clauses, but are always implied. If you include the implied exceptions in the declaration, your superclass method declaration could be written;

public int doIt(String str, Integer... data)
    throws ArrayIndexOutOfBoundsException, Error, RuntimeException {

That means, the explicit RuntimeException declaration on the subclass method is a subclass of an existing (implied) exception on the superclass method, so it's allowed.

Joachim Isaksson
  • 176,943
  • 25
  • 281
  • 294
0

If super class method does not declare any exception, then sub class overridden method cannot declare "checked" exception but it can declare "unchecked" exceptions

Nithin Devang
  • 69
  • 1
  • 8