Timing of a constructor's call to its superclass' constructor
09/26/2006
Editor's note: Sometimes the most interesting discussions begin when someone says, "This may be a stupid question, but ...." If the person asking the question has taken the time to think about the problem before asking, the question is often not stupid at all. The uncertainty points out an ambiguity in the specs, holes in the docs, or a search for how more experienced programmers might address a particular problem. From time to time, we will print one of the "(Not So) Stupid Questions" we receive and invite our readers to answer the question in the feedback section.
Remember that new people are joining the Java community all the time and may be looking for help from those with more experience. Also, those who began with Java as their first language can benefit from those coming to the community with experience in other languages. As always, answer the questions with kindness. You are also welcome to submit your questions to
This may be a stupid question, but ... "Why do constructors have to start with a call to super()?"
First thoughts:
This is more of a "why" than a "how" question. Any call to the constructor of a superclass must come on the first line of the constructor of the subclass. I frequently find that it would be handy to be able to prepare some values or objects to initialize a superclass with and find this a bit of a frustrating feature of Java. Does anyone know why this feature exists?
I am totally stumped for a good reason why this might be, but a very superficial guess might be that internally in the compiler, this makes some sort of simplification or optimization. Unfortunately, what I know about the internal workings of the JVM and Java compiler would comfortably fit on the back of a stamp, so that's about as far as I can go.
Still, it can be really inconvenient to not have control over when the superclass constructor gets called, so someone please tell me:
Why can I only call a superclass' constructor as the first statement of the subclass' constructor?
You would not BELIEVE how helpful it was for me to consciously DECIDE to ask questions with a girl tonight. It helped TREMENDOUSLY. I learned so much. It sounds so fucking simple but I talked SO much usually that I didnt get the info I needed so I could use that info back to her. mysteryseduceamogflirtpickup
With so many possibilities, in compiler and JVM to avoid enforcing calling super() first; am I in a minority, here, to pity the compiler writer, who has to take care of so many conditions.( if , god forbid, this were to become a JSR )
What if some one used called super inside -
1) an if statement?
2) a switch statement?
3) inside a for or while or do...while loop?
4) inside a try...catch block?
5) Inside the code of an Anonymous class ( outer.super())? -- ok this may be bit far fetched!
We need to include not only compiler writers, but also the developers -- who also need to understand and internalize these rules - in our pity list.
Given the possibilities, I wouldn't be surprised if someone (Josh Bloch?) wrote a super-hit book, "Effective Constructors"
:)
a counterexample
2006-09-27 10:53:26 javafreak
[Reply | View]
Not an explanation, but consider this ...
if super() could be called after the first statement in the subclass constructor, what would this code do?
class Y extends X {
public Y(int a) {
if (a < 2) {
super(a);
} else {
// don't call super(int a);
}
}
So X would not be initialized if a >= 2. Or is the compiler supposed to figure out that it should insert a call to the constructor for X in the else block??!!
not a counterexample?
2006-09-27 14:50:10 asjf
[Reply | View]
this is a good idea, but am not sure its correct..
The compiler could perform the same analysis it does for Local Variable Initialisation, and just be safe and reject code its unsure about, rather than try and be anywhere near accurate.
You could even allow different branches to call super(*) or this(*) by inductive hypothesis
not a counterexample?
2007-07-16 21:27:14 3ufblogg
[Reply | View]
Static has nothing to do with it
2006-09-27 08:05:18 smbell
[Reply | View]
@ricky_clarkson
Sorry, but static fields and methods have nothing to do with calling the super constructor. Static members are class members and not associated with an instance. Most of your post seems to confuse static access with object creation. Static members are garunteed to be initialized once and only once when the class is loaded into the JVM. This happens before any instance is created.
The super requirement has to do with consistent object state. An instance is make up of it's local members as well as the members of it's super classes. Unless the super classes are instansiated the subclass would be left in an inconsistent state.
Static has nothing to do with it
2006-10-03 03:34:35 ricky_clarkson
[Reply | View]
I'm not confused about object creation, as it happens.
You can call a static method from within the super(), e.g., super(prepareStuffToGiveTheSuperConstructor(args));
The memory for an object is allocated. All the fields are null/0/false. Then the constructors run. Of course it makes sense to invoke super, I never said anything to contradict that.
This isn't instantiating the superclasses, by the way, it is part of instantiating an object to run the constructors from its superclass.
Because it's simpler that way
2006-09-27 05:46:22 ricky_clarkson
[Reply | View]
If the language allowed statements before super(), then there would have to be a restriction to say that non-static members could not be accessed, as those would not have been initialised yet.
It has nothing to do with superclass constructors throwing exceptions.
The only reason to do anything before super() is to be able to pass it to super(), so this can be done inline, possibly by calling a static method:
class X
{
public X(String s)
{
}
}
class Y extends X
{
public Y(String s)
{
super(toLowerCase(s));
}
I don't come across any of these problems in my daily code, because I don't use explicit constructors. I use anonymous classes.
Just to debunk some of the other comments:
"The compiler is also responsible for inserting a call to super() as the first line in any constructor, if we fail to provide one - using an invokespecial instruction."
Lines in generated bytecode are fairly meaningless. invokespecial does not need to be the first bytecode instruction.
"The contract of a constructor is that the object will be in a known state after the constructor is finished."
The state of an object is defined at all times; Java defines everything.
"Until super() is invoked there is no instance hence no code can be executed within its context."
Simply untrue, an object is created before the constructor is called. This is demonstrable (probably not the most compact way of demonstrating this):
interface XRunnable
{
void run(X x);
}
class X
{
public X(XRunnable runnable)
{
runnable.run(this);
}
}
class Y extends X
{
static X staticX;
public Y()
{
super(new XRunnable()
{
public void run(X x)
{
staticX=x;
throw new RuntimeException();
}
});
}
}
class TempMain
{
public static void main(String[] args)
{
try
{
new Y();
}
catch (RuntimeException exception)
{
System.out.println(Y.staticX);
}
}
}
An instance is printed, not null.
"I guess the language specification just goes the safe way here by disallowing any code before the superclass aspects have been initialized."
Nope, it disallows any operations on 'this', specifically, and mandates that super is the first statement.
Cheers.
Because it's simpler that way
2006-09-27 08:55:49 vivekbp
[Reply | View]
It has nothing to do with superclass constructors throwing exceptions.
Hmm.. Try creating a derived class object if the super class constructor throws an exception. You can't! Compiler will not allow you to specify try before super. You're forced to declare that the derived class constructor throws it too.
It gives a clean exit for super class exceptions.
If super wasn't forced to be the first statement, some smart(?) programmer would try and catch the superclass exceptions, and leave the object in an dangerous inconsistent state.
Because it's simpler that way
2006-10-03 03:36:19 ricky_clarkson
[Reply | View]
You can't catch it from within the constructor, sure, but you can observe the instance, as the code I posted demonstrated.
Because it's simpler that way
2006-09-27 05:49:05 ricky_clarkson
[Reply | View]
An attempt at making the code more legible:
class X
{
public X(String s)
{
}
}
class Y extends X
{
public Y(String s)
{
super(toLowerCase(s));
}
private static String toLowerCase(String s)
{
return s.toLowerCase();
}
}
Second code snippet
interface XRunnable
{
void run(X x);
}
class X
{
public X(XRunnable runnable)
{
runnable.run(this);
}
}
class Y extends X
{
static X staticX;
public Y()
{
super(new XRunnable()
{
public void run(X x)
{
staticX=x;
throw new RuntimeException();
}
});
}
}
class TempMain
{
public static void main(String[] args)
{
try
{
new Y();
}
catch (RuntimeException exception)
{
System.out.println(Y.staticX);
}
}
}
Because it's simpler that way
2007-03-16 12:09:31 dividezero
[Reply | View]
hmm... one question about your use of this.
class X
{
public X(XRunnable runnable)
{
//here be implicit call to super();
runnable.run(this);
}
}
this doesn't exist before the super call.
supporting evidence
private class mak{
public mak(int i){
}
}
private class foo extends mak{
private int flab;
public foo(){
super(this.flab);
}
}
the this call in the super errors out, because there isn't a this yet.
therefore before the call to the super, there is no object created. in fact it makes a lot of sense.
concider construction of an object, if you start at the top of the type hierarchy and move down, then youc an also be detecting type problems, while making sure everything has been constructed correctly. and with the proper shadowing.
hehe, qed.
Its a requirement to ensure proper initialization
2006-09-26 18:04:49 ganeshread
[Reply | View]
We all know that the compiler is responsible for providing a default constructor if we dont provide one. This is called an <init> method in JVM parlance.
The compiler is also responsible for inserting a call to super() as the first line in any constructor, if we fail to provide one - using an invokespecial instruction.
The next responsibility of the compiler is to insert default initialization instructions between the call to the super() and user-defined initialization. This ensures that the user-defined initialization always executes only after the compiler-defined default initialization executes. This way, the possibility of using unitialized garbage variables is removed.
So. if we dont call super() (and assuming that the compiler doesnt insert one on the top for you) and start using some variables from the superclass, then the possibility of using garbage data remains, which is against the rule. I think, that is the reason why, we are not allowed to call super() or this() anywhere other than the first line. Just my 2 cents.
Its a requirement to ensure proper initialization
2006-09-27 14:58:30 asjf
[Reply | View]
hm, the lang spec. guarantees you're never in danger of getting garbage data in fields - i.e. before *any* constructor is invoked fields are initialized to default values (0 or null)
I think it's part of the language design.
2006-09-26 11:29:16 joshy
[Reply | View]
We won't know for sure until Josh Bloch posts :) but I think this is part of the language design. The contract of a constructor is that the object will be in a known state after the constructor is finished. If you could put code in your own constructor before the call to super() then you could call some methods on the super class before it's constructor was called, meaning everything in the super object may not be in a known state. This contract, that a constructor must finish completely before the object may be manipulated, is enforced by the compiler. Without it you could end up with a lot of very strange errors that would depend on your particular objects and might be thread dependent.
Constructors execute the context of an instance
2006-09-26 08:32:09 jattwood
[Reply | View]
I think this is down to the JVM, not the compiler. Constructors are special as they look like static methods from the caller's point of view, but actually execute as instance methods rather than static ones. Until super() is invoked there is no instance hence no code can be executed within its context.
However, you can execute arbitrary expressions to set up the parameters to super(), and these can invoke other methods (and other classes) if necessary. These will be executed as static code and their return values sent to the parent's constructor. Once the instance exists, you can do anything you like.
public class MyChild extends myParent {
public MtChild(int foo, String bar) {
Constructors execute the context of an instance
2006-09-26 08:36:00 jattwood
[Reply | View]
Sorry, tried to correct a typo and browser submitted the post.
public class MyChild extends MyParent {
public MyChild(int foo, String bar) {
super(foo * 12 / 100, bar.substring(7));
}
}
There is a workaround
2006-09-26 08:06:14 vivekbp
[Reply | View]
I believe the restriction is sensible and provides safety. Derived classes being more specific tend to be more heavyweight than the Super classes. If a super class constructor throws an exception, what's the point in creating derived (class) object?
It also ensures that super class methods can be called in the derived class constructor without much run-time checking overhead (whether super class object got created or not).
As regards writing sophisticated Super class initialization inside the derived constructor, IMO, it's a bad practice to put too much code into the constructor. If you do need such sophistication, you can write a static Factory method to do it.
The only time I found this restriction annoying was, when I needed reference to Objects created (and passed) during Super() invocation, which weren't part of the Derived class constructors signature. [ I had to use a thirdparty library with mostly private fields!]. I worked around using Constructor overloading and constructor chaining.
I provided a public constructor as intended. Chained it to a private constructor mimicking Super class constructor using this(). Private constructor would call Super() and create the objects in this call, and pass it on to super class and I get to hold the references to the created object(s) in the private constructor.
Superclass has to be initialized first
2006-09-26 04:10:58 peterbecker
[Reply | View]
My understanding of the reasons behind this is that the compiler always executes a constructor of the superclass first before any part of the subclass gets executed. This is required since otherwise access to the fields is not safe. Of course you could in theory do some calculations that do not involve the objects's state, but I guess the language specification just goes the safe way here by disallowing any code before the superclass aspects have been initialized.