Using 'super' to Call a Superclass Constructor
A constructor can call another constructor in the same class by writing this(...) as the very first line, so the other constructor's body runs and the caller does not repeat its code.
Why Repeated Setup Code Is a Problem
Many classes need more than one way to build an object. Some constructors accept many options, while others accept only a couple of values and fill in the rest with fixed defaults. Every one of these constructors usually has to perform the same essential setup. If each constructor repeats the full setup, the same logic appears in several places, and every change has to be made in all of them so they stay in sync.
Java offers a way out. One constructor can hand its work to another constructor in the same class by writing this(...) as the very first line. This article follows a real chain of constructors to see how the calls connect, then looks at the related keyword super, which lets a subclass constructor reuse the constructor of its superclass. Before reading the explanation, keep in mind the question this article answers: when a constructor passes its work along, which constructor body runs first and which one runs last?
Tracing a Chain of Constructor Calls
The source uses a MosaicCanvas class, which represents a grid of colored rectangles. Its main constructor takes four parameters: the number of rows, the number of columns, a preferred block width, and a preferred block height. Every object of this class needs the full initialization that the main constructor performs. The author wanted easier constructors with fewer options, so the class gains two shorter constructors. Each one exists only to call another constructor while supplying constant values for the parameters the caller does not provide.
- 1Line 1 of the no-argument constructor is
this(42, 42), which starts the first hop of the chain. - 2Line 1 of the two-argument constructor is
this(rows, cols, 16, 16), which forwards the values to the main constructor. - 3The main constructor has no
this(...)call, so the chain stops there and its body performs the initialization.
- The no-argument constructor forwards the fixed values 42 and 42 to the two-argument constructor.
- The two-argument constructor forwards the caller's rows and columns, plus the fixed block size 16 and 16, to the main constructor.
- The four-parameter constructor is the end of the chain and does the real initialization.
Each shorter constructor is a small forwarding step. The no-argument constructor passes 42 and 42 onward. The two-argument constructor passes the caller's rows and columns onward, together with the fixed values 16 and 16. The chain always ends at the four-parameter constructor. The source states that this(42,42) calls the two-parameter constructor, which in turn calls the main four-parameter constructor. The main constructor is eventually called in every case, and that is what guarantees all of the essential initialization happens no matter which constructor the caller used. The shorter constructors skip no setup. They only supply values that the caller did not provide.
What do you think happens?
A caller runs new MosaicCanvas(). Of the three constructor bodies, which one finishes first, and which one is the last to finish?
Reveal answer
The main four-parameter body finishes first, and the no-argument body finishes last.
Each this(...) call transfers control to the called constructor, and the calling constructor resumes only after that call returns. The entry point is entered first, but the innermost constructor, the main one at the end of the chain, is the first body to complete. The remaining statements of the shorter constructors run afterward, in reverse order of the calls.
- 1Start at the constructor the caller invoked and note the arguments it passes in its
this(...)call. - 2Follow each
this(...)call to the next constructor, writing down the arguments received at every hop. - 3Stop at the main constructor, where the chain ends and the essential initialization is performed.
- 4If a value is unexpected, check the hop where a constant was supplied, or the main constructor where that parameter was used.
The First-Line Rule for this(...)
The chaining mechanism depends on where the this(...) call appears. The call must be the very first line of the constructor. Any statement placed before it breaks this rule, so the call cannot be moved lower in the constructor to make room for setup code of its own. Beginners often forget this position, or misread what the call does, and this is the source of several common errors.
- The statement that computes area comes before the
this(...)call. - The compiler rejects the constructor, because
this(...)must be the first statement.
Why Subclasses Do Not Inherit Constructors
Many learners who have just met inheritance assume that a subclass gets everything its superclass has, including the constructors. A subclass does inherit fields and methods, so it seems natural that it would inherit the ways of building an object as well. This belief feels reasonable, and it causes confusion the first time code does not behave as expected.
What do you think happens?
The superclass Shape has only one constructor, which takes a String. The subclass Circle has its own constructor, but that constructor does not call super. What happens when the code is compiled?
Reveal answer
It fails to compile, because the implicit super call has no matching superclass constructor.
Constructors are not inherited, so Circle does not receive Shape's String constructor. When Circle's constructor has no explicit super call, Java looks for a superclass constructor that takes no parameters. Shape has none, so the compiler reports an error.
When you extend a class to form a subclass, the constructors of the superclass do not become part of the subclass. If the subclass needs constructors, you have to define them from scratch. There is one more rule that matters for new classes. If you do not define any constructor in the subclass, the computer provides a default constructor for you, and that default constructor takes no parameters.
This arrangement can cause real trouble when the superclass constructor does a lot of necessary work. A subclass that needs that work done might seem to require repeating all of it. The problem is sharper when you do not have the superclass source code, or when the superclass constructor relies on private member variables the subclass cannot access. The fix is to let the subclass constructor reuse the superclass constructor directly. Java provides the super keyword for that purpose.
Calling a Superclass Constructor with super
The special keyword super lets a subclass constructor call a constructor of its superclass. The call is written as super followed by a parenthesized argument list, such as super(3,4);. As with this(...), the call must be the very first statement in the subclass constructor. The notation looks like a method call, which can be misleading. super is not a subroutine, and constructors cannot be called the way other subroutines are called. The construct is valid only at the start of a constructor.
- 1The call new
Square(5)enters Square's constructor with side equal to 5. - 2The first statement,
super(5, 5), transfers control into Shape's constructor with width and height both set to 5. - 3When Shape's constructor finishes, control returns to Square's constructor, which then runs any remaining statements of its own.
- Shape has a single constructor that takes two int arguments.
- Square's constructor begins with
super(side, side), which runs the Shape constructor first. - Shape's fields are set by Shape's constructor, not by Square's constructor.
The diagram shows the order of events. The subclass constructor starts, and its first statement is the super call. Control moves into the superclass constructor, which runs with the two integer arguments. When that constructor finishes, control returns to the subclass constructor, which then runs the rest of its own statements. The superclass work comes first because the super call must be first.
What Java Does Without an Explicit super Call
If a subclass constructor does not explicitly call a superclass constructor with super, Java calls the superclass constructor that has no parameters, and it does so automatically. This call is inserted before the subclass body runs. The rule has a second half. If the superclass has no no-parameter constructor, the missing call is reported as a syntax error. The programmer must then either add a no-parameter constructor to the superclass, or write an explicit super call that matches one of the superclass constructors.
- Square has no super line, so Java tries to insert
super()as the first action. - Shape has no no-parameter constructor, so this code does not compile.
Mistakes Beginners Make with Chained and Super Calls
Common mistake Assuming a subclass inherits its superclass constructors
Why it failsConstructors are not inherited, so a subclass must define its own constructors.
Do this insteadWrite a subclass constructor that reaches the superclass constructor through super(...).
Common mistake Putting setup code before this(...) or super(...)
What it looks likeA statement that computes a value is written above this(rows, cols, 16, 16).
Why it failsThis call must be the very first statement, so any earlier statement makes the code invalid.
Do this insteadMove the statement into the constructor that does the work, or compute it inside the main constructor body.
Common mistake Treating super(...) as an ordinary method call
Why it failssuper is a construct valid only at the start of a constructor, not a subroutine.
Do this insteadPlace super(...) as the first line of the subclass constructor.
Common mistake Leaving out super when the superclass has no no-parameter constructor
Why it failsJava inserts a call to the no-parameter superclass constructor, and if none exists the compiler reports a syntax error.
Do this insteadAdd a no-parameter constructor to the superclass, or write an explicit super call that matches one of its constructors.
Common mistake Assuming a chained value is wrong in the entry constructor when the problem is further down
Why it failsThe value passed through each hop can change, and the main constructor is where the parameter is used.
Do this insteadTrace each this(...) call from the entry constructor to the main constructor and check the arguments at each hop.
Practice Writing a Chained Constructor
A class Tile has a main constructor Tile(int width, int height, String color). Write a second constructor Tile(int size) that gives the caller a square tile of the given size with the color "white" by calling the main constructor. Then write a subclass BorderedTile that extends Tile and has a constructor BorderedTile(int size) which passes size along to Tile using super. Check that each this(...) and super(...) call is the first line of its constructor.
Hints
- Use
this(size, size, "white")as the first line of the one-argument constructor. - Use
super(size)as the first line of BorderedTile's constructor, and check that Tile has a matching constructor. - If the compiler complains, check whether any statement appears above the this or super call.
Key Takeaways
- A constructor can call another constructor in the same class by writing
this(...)as the very first line, so the shared initialization is written once in the main constructor. - In a chain of
this(...)calls, the main constructor is always reached, and it is the first body to finish, with the entry constructor's remaining statements running last. - Constructors are not inherited, so a subclass defines its own constructors and reaches superclass constructors through
super(...), which must be the first statement. - If a subclass constructor has no explicit super call, Java inserts a call to the superclass no-parameter constructor, and if that constructor does not exist the compiler reports a syntax error.