Take the 2-minute tour ×

In the following code:

class MyException extends Exception{}

interface Bread
    public void eat() throws MyException;

interface Fringe 
    public void eat() throws RuntimeException;

public class Test implements Fringe , Bread // #5
    public static void main(String[] args)
        Fringe best = new Test(); // #1
        best.eat();// #2

    public void eat() throws RuntimeException // #3
        throw new RuntimeException(); // #4

MyException is not a RuntimeException. Why we can declare Test.eat() as throwing a RuntimeException but not a general Exception?

share|improve this question
Are you sure this is the corrent code? MyException isn't actually thrown anywhere here. –  cha0site Jan 18 '12 at 12:08
add comment

3 Answers

Two points:

  • You cannot declare it to throw Exception, because it would then throw a more general exception than what the eat() method in the Bread interface specifies. A method inherited from a superclass or interface cannot throw more general exceptions than what is specified in the superclass or interface.
  • You can declare it to throw RuntimeException because methods can always throw unchecked exceptions, whether you specify them in a throws clause or not. (So specifying that it can throw RuntimeException is redundant).

To explain the reason for the rule I mentioned in the first point: Suppose you do this:

// Allowed because Test implements Bread
Bread obj = new Test();

If you now call obj.eat(), the compiler needs to check if you correctly handle all checked exceptions that might happen in that call. It does this by looking at the type of the variable obj, which is Bread. The Bread interface specifies that eat() can throw MyException (and implicitly, subclasses of MyException).

If your Test.eat() method were allowed to throw a more general kind of checked exception, such as Exception, then the compiler cannot check by just looking at the type of obj that you handle all checked exceptions correctly.

To prevent this problem, the rule is that an overridden method is not allowed to throw more general exceptions.

share|improve this answer
add comment

An overriding method can only throw those exceptions which satisfy IS-A relationship with the exception thrown in overriden method.

If you try to throw Exception in your class while interface throws MyException ... compiler sees if following statement is true:

Exception IS-A MyException -- and it's false, you know. so compiler rejects it.

Hence you can throw only a more-specific exception from a method in sub-class.

for you question about RunTime Exception:

For throwing RunTime exception, it is equivalent to as if you've not written it explicitly. so compiler ignores it. because even if you don't mention it a method can throw exception at Runtime.

share|improve this answer
add comment

This is because in the overriding method, you can only throw exceptions below or equal to the exception defined in your contract. So, eat() can throw MyException and its subclasses but not anything above MyException which is what Exception is. Runtime exceptions are not a part of this rule and you can freely throw them since they are not "checked".

This is because let's say I'm using the Bread interface to access the instance of Test class. If I call the eat() method, I can "check" for MyException since it's part of the contract but if the underlying implementation decides to throw a "higher" exception, it won't be caught within my MyException catch block thus violating the contract. Have a look at the below code for an example:

Bread b = new Test();
try {
  // if this throws Exception, it won't be caught in the catch block
  // thereby violating contract
} catch (MyException e) {
share|improve this answer
add comment

Your Answer


