Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subclassing from classses with Java Constructors throwing Exceptions

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
}
like image 739
user1529412 Avatar asked Feb 23 '15 16:02

user1529412


2 Answers

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.

like image 193
Sotirios Delimanolis Avatar answered Oct 23 '22 20:10

Sotirios Delimanolis


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.

like image 37
Hoopje Avatar answered Oct 23 '22 21:10

Hoopje