My understanding is that overriding method in subclass should throw no exception or narrower exception from that on base method of parent class. Why does it work the opposite in constructors, the constructor of subclass has to throw the same exception or wider, Any reasonable explanation for this?
class MyException extends Exception{}
class MySubException extends MyException{}
class MySubSubException extends MySubException{}
public class Alpha {
public Alpha() throws MyException{
}
void foo() throws MyException {}
}
class Beta extends Alpha{
public Beta() throws MyException{ //NOT MySubSubException
super();
}
void foo() throws MySubException {} //Ok for methods
}
Why does it work the opposite in constructors, the constructor of subclass has to throw the same exception or wider, Any reasonable explanation for this?
A subclass constructor always invokes its parent constructor with a call to super(..)
. In this case, the parent constructor is declared as throwing a checked exception of type MyException
. Your subclass constructor must be able to handle that (with a throws
since super(..)
has to be the first statement in the constructor body).
With methods, you're not forced to invoke the super
implementation.
The declared exceptions of a method are part of its public contract. The declared exception are exceptions that may be thrown by the method, but it is not the case that they must be thrown by the method. Overriding methods need not have the exact same signature as the method they override; they can have a less restricted signature.
Consider the following example:
class A {
A f() throws MyException { ... }
}
class B {
@Override
B f() throws MySubException { ... }
}
class C {
void g(A a) {
...
}
}
Here, the method f
of class B
overrides method f
of class A
although it does not have the exact same signature. But all instances of B
fulfill the contract of A
, because the method B.f
indeed returns an A
instance and cannot throw an checked exception except when it is a subclass of MyException
. Thus, we can safely pass a B
instance to any method that asks for an A
reference, such as g(A a)
in the C
class.
For constructors this is not the case. First, constructors do not belong to instances, they belong the class, and constructor never override another constructor. But they do always (implicitly or explicitly) call the constructor of a superclass. When this constructor declares checked exceptions, then the constructor must either handle them with a try-catch
block, or declare them itself.
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