The terribly misunderstood super()

For developers new to Java, here's a tip that could make you look more like a ninja coder than colleagues who have been writing Java for years: learn how super() works within constructors.

I say this because I recently completed a yearlong project with 12 developers and found during the staffing process that about one third of the developers I interviewed, many of whom had been coding Java professionally for years, misunderstood fundamental concepts of Java object creation. Some of these smart developers would insist during the job interview that unless a Java constructor explicitly invokes super(), the parent constructor would never be called. With such an important Java language feature being so terribly misunderstood, I thought I'd dust off this blog with a reminder to those new to Java of how super() works in constructors. A related topic would be how this(...) works, but I'll leave that for another time.

Rule: You never, ever, have to call the no-argument super().

Corollary: It is impossible to instantiate an object without at least one constructor being invoked in all parent classes.

With this rule in mind, here is code to illustrate.
public class A {
public A() {
System.out.println("A says hello");
}
}
public class B extends A {
public B() {
System.out.println("Hello from B");
}
}
If you instantiate class B like this:
B myB = new B();
the console will output:
A says hello
Hello from B
Since B's constructor didn't specify a different constructor in class A by using super with an argument list, the Java runtime invoked A's no-argument constructor by default. No call to super() is needed from within B's constructor in order for the A parent class to be instantiated. In fact, there is absolutely, positively no way to create a B instance without creating an A instance first.

If I modify class B to add super():
public class B extends A {
public B() {
super();
System.out.println("Hello from B");
}
}
the output would be identical to the first version. In fact, the generated Java bytecode would be identical. When there is no explicit call to super() as the first statement in a constructor, the Java compiler implicitly adds a call to the no-argument super() to invoke the no-argument constructor of the parent class. There is never a need to add an explicit call to a no-argument super().

I think a lot of Java developers end up believing you need to call super() in order for the superclass's constructor to be called because so much Java code out there includes extraneous calls to super(). For instance, here is a constructor taken verbatim from a Hello World J2ME coding example from Research in Motion Ltd., the makers of the BlackBerry smart phones.
//create a new screen that extends MainScreen, which provides
//default standard behavior for BlackBerry applications
final class HelloWorldScreen extends MainScreen
{
public HelloWorldScreen()
{
//invoke the MainScreen constructor
super();
//add a title to the screen
LabelField title = new LabelField("HelloWorld Sample", LabelField.ELLIPSIS
| LabelField.USE_ALL_WIDTH);
setTitle(title);
//add the text "Hello World!" to the screen
add(new RichTextField("Hello World!"));
}
If I were a developer just learning Java, I would assume the call to super() is required in order to invoke the parent class's constructor. Why else would the HelloWorldScreen developer code it, and add that comment to explicitly point out the call to the parent class? I searched Krugle for open source projects using calls to the no-argument super() and found 82,347 Java files, including code from major projects like Eclipse and GlassFish. It seems many developers like explicitly invoking super().

I can see one possible reason for doing so. Perhaps there are several constructors in the parent class and the developer wants to call out that he or she is using the no-argument version. The first danger I see with adding extra code that adds no behavior to a program is the risk of adding confusion. For instance, I recently ran across code with constructors that looked something like this:
public class SpecialClass extends RegularClass {
private int x, y;
public SpecialClass() {
super();
}
public SpecialClass(int x) {
super();
this.x = x;
this.y = 0;
}
public SpecialClass(int x, int y) {
this.x = x;
this.y = y;
}
}
The first two constructors explicitly called super(), but the third constructor didn't. Was that a mistake? Did the developer mean to add a call to a different superclass constructor, like super(x, y), but forgot? If not, why did he leave off the third call to super()?

Finding small inconsistencies in code like this waste development time as the reader tracks down whether the inconsistency was the result of harmless oversight or the result of an error that is now a bug. Code that doesn't do anything, without a documented reason for being there, seems way more hazardous to understanding code than any value I can see that might be gained from "documenting" that you really meant the automatic behavior to be taken by writing extra code. Similar to seeing a class that extends java.lang.Object, I end up asking why did the developer do that.

(If you use super() regularly for documentation purposes, I would appreciate hearing your reasons.)

The second danger in adding extraneous calls to super() is that it seems to be teaching a lot of new Java developers that super() is required in order for parent constructors to be invoked. At least that certainly is my recent experience from interviewing Java developers.

The only time super is required is when it takes a non-empty argument list to invoke a constructor in the parent class that requires parameters. For example, here is my base class to represent a knight from the movie Monty Python and the Holy Grail. Note that the constructor requires an argument.
public class EnglishKnight {
private String whatISay;
public EnglishKnight(String saying) {
whatISay = saying;
}
@Override
public String toString() {
return whatISay;
}
}
This following subclass (with an error) is meant to be a certain kind of knight from the movie:
public class KnightWhoSaysNeep extends EnglishKnight {
public KnightWhoSaysNeep() {
// syntax error here.
}
}
You probably see the compile-time error. Since KnightWhoSaysNeep extends EnglishKnight, and since EnglishKnight does not contain a no-argument constructor, the KnightWhoSaysNeep class must override the implicit (and illegal) call to super() in its constructor. Here's the error from Eclipse:
Implicit super constructor EnglishKnight() is undefined.
Must explicitly invoke another constructor
To fix KnightWhoSaysNeep we need to call one of the valid constructors in the superclass. In this case, there is only one constructor in the superclass, which takes a String as an argument.
public class KnightWhoSaysNeep extends EnglishKnight {
public KnightWhoSaysNeep() {
super("Neep!");
}
}
The corrected KnightWhoSaysNeep class demonstrates the proper use of super -- one that takes a parameter to override default behavior.