OCA Java SE 8 Class Design - Java Constructor Inheritance








Defining Constructors

In Java, the first statement of every constructor is either a call to another constructor within the class, using this(), or a call to a constructor in the direct parent class, using super().

If a parent constructor takes arguments, the super constructor would also take arguments.

We use both super() and super(age) in the following example:

class Shape { 
  private int edge; 
  public Shape(int edge) { 
    super(); 
    this.edge = edge; 
  } 
} 

class Rectangle extends Shape { 
  public Rectangle(int edge) { 
    super(edge); 
  } 
  public Rectangle() { 
    this(4); 
  } 
} 

In the first class, Shape, the first statement of the constructor is a call to the parent constructor defined in java.lang.Object, which takes no arguments.

In the second class, Rectangle, the first statement of the first constructor is a call to Shape's constructor, which takes a single argument.

The class Rectangle also includes a second no-argument constructor that doesn't call super() but instead calls the other constructor within the Rectangle class using this(4).

super() command may only be used as the first statement of the constructor.





Example

For example, the following two class definitions will not compile:

The following class will not compile because the call to the parent constructor must be the first statement of the constructor, not the second statement.

class Main { 
  public Main() { 
    System.out.println("Main created"); 
    super(); // DOES NOT COMPILE 
  } 
} 

In the following class, super() is the first statement of the constructor, but it also used as the third statement.

Since super() can only be used as the first statement of the constructor.

class Main { 
  public Main() { 
    super(); 
    System.out.println("Main created"); 
    super();  // DOES NOT COMPILE 
  } 
} 

If the parent class has more than one constructor, the child class may use any valid parent constructor in its definition.

class Shape { 
  private int edge; 
  private String name; 
  public Shape(int edge, String name) { 
    super(); 
    this.edge = edge; 
    this.name = name; 
  } 
  public Shape(int edge) { 
    super(); 
    this.edge = edge; 
    this.name = null; 
  } 
} 
class Pentagon extends Shape { 
  public Pentagon(int edge) { 
    super(edge,"Pentagon"); 
  } 
  public Pentagon() { 
    super(5); 
  } 
} 




Compiler Enhancements

Java compiler automatically inserts a call to the no-argument constructor super() if the first statement is not a call to the parent constructor.

The following three class and constructor definitions are equivalent, because the compiler will automatically convert them all to the last example:

class Main { 
} 

class Main { 
  public Main() { 
  } 
} 

class Main { 
  public Main() { 
    super(); 
  } 
} 

No-argument constructor

What happens if the parent class doesn't have a no-argument constructor?

In this case, Java will not create one for you and you must create at least one constructor in your child class that explicitly calls a parent constructor via the super() command.

For example, the following code will not compile:

class Shape { 
  public Shape(int edge) { 
  } 
} 

class Rectangle extends Shape {  // DOES NOT COMPILE 
} 

In this example no constructor is defined within the Rectangle class, so the compiler tries to insert a default no-argument constructor with a super() call.

The compiler stops when it realizes there is no parent constructor that takes no arguments.

In this example, we must explicitly define at least one constructor, as in the following code:

class Shape { 
  public Shape(int edge) { 
  } 
} 

class Rectangle extends Shape { 
  public Rectangle() {  // DOES NOT COMPILE 
  } 
} 

This code still doesn't compile because the compiler tries to insert the no-argument super() as the first statement of the constructor in the Rectangle class, and there is no such constructor in the parent class.

We can fix this, though, by adding a call to a parent constructor that takes a fixed argument:

class Shape { 
  public Shape(int edge) { 
  } 
} 

class Rectangle extends Shape { 
  public Rectangle() { 
    super(10); 
  } 
} 

Subclasses may define no-argument constructors even if their parent classes do not, provided the constructor of the child maps to a parent constructor via an explicit call of the super() command.

Constructor Rules

super() must be used as the first statement of the constructor.

If the parent doesn't have a no-argument constructor, the compiler requires an explicit call to a parent constructor from child constructor.

The first statement of constructor must be this(), or super().

If super() is declared in a constructor, Java will insert a no-argument super() as the first statement of the constructor.

If the parent class has only constructor with argument and the child doesn't define any constructors, the compiler will throw an error.

Calling Constructors

Java parent constructor is always executed before the child constructor.

For example, try to determine what the following code outputs:

class Shape { 
  public Shape() { 
    System.out.println("Shape"); 
  } 
} 

class Rectangle extends Shape { 
  public Rectangle() { 
    System.out.println("Rectangle"); 
  } 
} 

public class Main extends Rectangle { 
  public static void main(String[] args) { 
    new Main(); 
  } 
} 

The compiler first inserts the super() command as the first statement of both the Shape and Rectangle constructors.

Next, the compiler inserts a default no-argument constructor in the Chimpanzee class with super() as the first statement of the constructor.