Reputation: 217
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
{
System.out.println("Test");
throw new RuntimeException(); // #4
}
}
MyException
is not a RuntimeException
. Why we can declare Test.eat()
as throwing a RuntimeException
but not a general Exception
?
Upvotes: 2
Views: 255
Reputation: 206906
Two points:
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.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.
Upvotes: 2
Reputation: 13882
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.
Upvotes: 0
Reputation: 23218
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
b.eat();
} catch (MyException e) {
e.printStacktrace();
}
Upvotes: 4