I am using Java 7 and came across something very interesting. While extending the java.lang.Appendable interface with an interface of my own, I am overriding each method explicitly for documentation purposes more than anything.
All three methods defined in java.lang.Appendable throws IOException which I thought my overriding methods would also have to declare. However, I ended up deleting the throws clause on one of the overridden methods and strangely enough the Java 7 compiler didn't complain about the missing declaration. So I went ahead and deleted the throws clause from the other two methods and again, no complaints from the compiler.
So why can I override a method in an interface and remove its throws clause? And when did this phenomenon become legal in Java?
An overriding method can throw any unchecked exceptions, regardless of whether the overridden method throws exceptions or not. However, the overriding method should not throw checked exceptions that are new or broader than the ones declared by the overridden method.
We need to follow some rules when we overriding a method that throws an Exception. When the parent class method doesn't throw any exceptions, the child class method can't throw any checked exception, but it may throw any unchecked exceptions.
You can make the methods default in the interface itself, Default methods are introduced in interfaces since Java8 and if you have default methods in an interface it is not mandatory to override them in the implementing class.
The parent interface declares that the method might throw an exception. An implementation that does not throw the exception conforms to one that might. Your interface is declaring that implementations do not in fact throw exceptions, while still adhering to the contract of the parent interface.
Code that assigns your instances to an Appendable
variable will have to catch the exception as defined, while code that treats your instances as your child interface will not have to.
Put simply:
interface Foo {
void m() throws Exception;
}
interface Bar extends Foo {
@Override
void m();
}
void test(Foo foo, Bar bar) {
foo.m(); // must catch exception
bar.m(); // no exception declared to be thrown, so don't need to catch
}
Note also that it's the type of the variable, not the object that's important:
Foo foo = new BarImpl();
foo.m(); // must catch exception
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With