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().

While the B object is being instantiated in the call to new B(), the Java runtime also called the default no-argument constructor from the Object class before calling A’s constructor. Thus, the single statement B myB = new B(); caused three constructors to be run, and none of the constructors called super() for it to happen.

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(); // FROM COMMENT, DEVELOPER BELIEVES super() IS REQUIRED
        //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: parent class has no default constructor
    }
}

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.

Comments

  1. Jon said:

    It’s nii, not neep…
    HEAD KNIGHT: We are the keepers of the sacred words: Ni, Peng, and Neee-wom!
    RANDOM: Neee-wom!
    ARTHUR: Those who hear them seldom live to tell the tale!
    HEAD KNIGHT: The Knights Who Say ‘Ni’ demand a sacrifice!
    ARTHUR: Knights of Ni, we are but simple travelers who seek the enchanter who
    lives beyond these woods.
    HEAD KNIGHT: Ni!

  2. Lava Kafle said:

    Super!! I can’t resist the idea presented here . Too useful even for old geeks.

  3. Daniel Lindner on said:

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

    I have a reason. All my constructor code has one of two possible first lines (with or without parameters):

    • super(…)
    • this(…)

    Every deviation from this rule would be an error. This is handy in two cases:

    • POJOs with more than one constructor should have one constructor beginning with super(…) and all other ones beginning with this(…). That way, proper object initialization is ensured.
    • Classes that inherit from multi-constructor superclasses and do not want to change the instantiation behaviour of it should have multiple constructors all beginning with super(…) and no this(…).

    With one look at the first lines of every constructor, you get a feeling what type of class your current code is. In a code review situation, this look ensures proper object instantiation in most cases (especially in combination with final members).

    I know that the reason isn’t strong and the extra code isn’t necessary. So its a matter of personal taste, with slightly better reasons to the “it’s bloat” attitude.

  4. Tom McQueeney on said:

    M,

    Thank you for challenging my statement. Section 12.5 of the JLS indeed supports your argument that only one instance is created.

    Conceptually, I have looked at object creation as having each superclass also instantiated as a separate object instance, but you have a good point that there is no need for separate object instances. The JLS says instance fields from superclasses become part of the object instance being created with the “new” keyword, which does not make sense if those superclasses were also being instantiated as separate objects.

    Conceptually, I wonder if looking at object creation as creating separate instances of the superclasses would lead to a nonsensical state of affairs. Since there is no way for a subclass to return to callers a reference to one of its (conceptual) superclass instances — e.g. you can’t say “return this.super;” — then the garbage collector would always free these conceptual instances when the subclass instance is freed. Can you think of an example when this conceptual world of separate object instances for superclasses would lead to a violation of the JLS?

    Again, thank you for posting your comment. I stand corrected about superclass object creation unless someone with expert knowledge of the Java runtime offers a better explanation.

    -Tom

  5. Anonymous on said:

    Hi Tom,

    Actually, i think the JLS is kinda vague (guess it should be…lol) so its up to the VM for interpretation and implementation.

    BTW, Thanks for the great post.

    Mike

  6. m on said:

    Hi..i don’t think there are 2 objects created when instantiating a subclass. An instance of the superclass will not be created. Please correct me if i’m wrong.

  7. Jos Horsmeier on said:

    An object is constructed like an onion, layer by layer and inner layers first. The implicitly created ‘super()’ call ensures that. There is one exception to the rule (which makes it an illegal construct): if all constructors of a class have a first line ‘this( … )’ no call to a superclass’ constructor is made and it is flagged as an error by the compiler.

    kind regards,

    Jos

Comments are closed.