Reputation: 173
I have a little dilemma here,
say I have a class
public class Child extends Parent implements Interface{
public static void main(String[] args){
Child child = new Child();
child.methodOne(); } }
where
abstract class Parent {
public void methodOne() {
System.out.print("cannot fly ");
}}
interface Interface {
public abstract void methodOne() throws Exception;}
There are no compilation errors with this structure
wherease if I did this
abstract class Parent {
public void methodOne() throws Exception {
System.out.print("cannot fly ");
}}
interface Interface {
public abstract void methodOne(); }
Two compliation errors rise saying
Exception Exception in throws clause of Parent.methodOne() is not compatible with Interface.methodOne()
and
Unhandled exception type Exception
which asks to add throws
or try/catch
in main
method
Why is that happening?
Upvotes: 1
Views: 1143
Reputation: 288
When you are doing this,
public class Child extends Parent implements Interface
But, when you are explicitly throwing an exception
in the Parent class
' method, you have to handle that exception when you make a call from the child object.
Upvotes: 3
Reputation: 589
Every time you implement an interface (or override a method from a parent class, same thing), you need to respect the contract of that interface. Respecting the contract means that you cannot throw more exceptions than in the interface declaration.
In both cases, Interface
is the contract, and Parent
is the implementation (via the "binding" between the two that happens in class Child
).
In the first case, the interface says that methodOne()
is allowed to throw Exception, but does not have to. Your actual implementation in Parent
does not throw anything, so it is a subset of the contract and is fine.
In the second case, the interface says that methodOne()
will not throw anything (*), hence any implementation consequently is not allowed to throw any exception. However, the implementation in Parent
asks to be allowed to throw, which is incompatible with the interface contract; hence the compiler error.
Also note in this second case that you could very well override methodOne()
in Child
with an empty throws
declaration so that the signature would conform to the interface contract. You could then call super.methodOne()
and rewrap Exception
as RuntimeException
(for example).
By the way:
throws
declaration of all interfaces;abstract
keyword in interfaces, because method declarations in interface are always abstract by nature.(*) except for RuntimeException's of course.
Upvotes: 4
Reputation: 2316
The throws
declaration is not part of the methodOne()
contract in the interface Interface
.
Whenever you implement an interface you must implement your method contracts, you can do this without adding the throws
declaration if the interface has a throws
declaration.
However you cannot add functionality that isn't stated in the Interface
contract.
You can fix the other error by modifying your main
method to also throw an Exception
:
public static void main(String[] args) throws Exception {
Child child = new Child();
child.methodOne();
}
or by surrounding the methodOne()
call in a try-catch
block:
public static void main(String[] args) throws Exception {
Child child = new Child();
try{
child.methodOne();
}catch(Exception e){
//do something to handle exception i.e. System.out.println(e.getMessage());
}
}
Additional reading: Java interface throws an exception but interface implementation does not throw an exception?
Excerpt:
A general rule of implementing and extending is you can make your new class or interface "less restrictive" but not "more restrictive". If you think of the requirement to handle an exception as a restriction, an implementation that doesn't declare the exception is less restrictive. Anybody who codes to the interface will not have trouble with your class.
Upvotes: 1