Super constructor must be a first statement in Java constructor [closed]
- by Val
I know the answer: "we need rules to prevent shooting into your own foot". Ok, I make millions of programming mistakes every day. To be prevented, we need one simple rule: prohibit all JLS and do not use Java. If we explain everything by "not shooting your foot", this is reasonable. But there is not much reason is such reason.
When I programmed in Delphy, I always wanted the compiler to check me if I read uninitializable. I have discovered myself that is is stupid to read uncertain variable because it leads unpredictable result and is errorenous obviously. By just looking at the code I could see if there is an error. I wished if compiler could do this job. It is also a reliable signal of programming error if function does not return any value. But I never wanted it do enforce me the super constructor first. Why?
You say that constructors just initialize fields. Super fields are derived; extra fields are introduced. From the goal point of view, it does not matter in which order you initialize the variables. I have studied parallel architectures and can say that all the fields can even be assigned in parallel... What? Do you want to use the unitialized fields? Stupid people always want to take away our freedoms and break the JLS rules the God gives to us! Please, policeman, take away that person!
Where do I say so? I'm just saying only about initializing/assigning, not using the fields. Java compiler already defends me from the mistake of accessing notinitialized. Some cases sneak but this example shows how this stupid rule does not save us from the read-accessing incompletely initialized in construction:
public class BadSuper {
String field;
public String toString() {
return "field = " + field;
}
public BadSuper(String val) {
field = val;
// yea, superfirst does not protect from accessing
// inconstructed subclass fields. Subclass constr
// must be called before super()!
System.err.println(this);
}
}
public class BadPost extends BadSuper {
Object o;
public BadPost(Object o) {
super("str");
this. o = o;
}
public String toString() {
// superconstructor will boom here, because o is not initialized!
return super.toString() + ", obj = " + o.toString();
}
public static void main(String[] args) {
new BadSuper("test 1");
new BadPost(new Object());
}
}
It shows that actually, subfields have to be inilialized before the supreclass! Meantime, java requirement "saves" us from writing specializing the class by specializing what the super constructor argument is,
public class MyKryo extends Kryo {
class MyClassResolver extends DefaultClassResolver {
public Registration register(Registration registration) {
System.out.println(MyKryo.this.getDepth());
return super.register(registration);
}
}
MyKryo() {
// cannot instantiate MyClassResolver in super
super(new MyClassResolver(), new MapReferenceResolver());
}
}
Try to make it compilable. It is always pain. Especially, when you cannot assign the argument later.
Initialization order is not important for initialization in general. I could understand that you should not use super methods before initializing super. But, the requirement for super to be the first statement is different. It only saves you from the code that does useful things simply. I do not see how this adds safety. Actually, safety is degraded because we need to use ugly workarounds. Doing post-initialization, outside the constructors also degrades safety (otherwise, why do we need constructors?) and defeats the java final safety reenforcer.
To conclude
Reading not initialized is a bug.
Initialization order is not important from the computer science point of view. Doing initalization or computations in different order is not a bug.
Reenforcing read-access to not initialized is good but compilers fail to detect all such bugs
Making super the first does not solve the problem as it
"Prevents" shooting into right things but not into the foot
It requires to invent workarounds,
where, because of complexity of analysis, it is easier to shoot into the foot
doing post-initialization outside the constructors degrades safety (otherwise, why do we need constructors?)
and that degrade safety by defeating final access modifier
When there was java forum alive, java bigots attecked me for these thoughts. Particularly, they dislaked that fields can be initialized in parallel, saying that natural development ensures correctness. When I replied that you could use an advanced engineering to create a human right away, without "developing" any ape first, and it still be an ape, they stopped to listen me. Cos modern technology cannot afford it. Ok, Take something simpler. How do you produce a Renault? Should you construct an Automobile first? No, you start by producing a Renault and, once completed, you'll see that this is an automobile. So, the requirement to produce fields in "natural order" is unnatural. In case of alarmclock or armchair, which are still chair and clock, you may need first develop the base (clock and chair) and then add extra. So, I can have examples where superfields must be initialized first and, oppositely, when they need to be initialized later. The order does not exist in advance. So, the compiler cannot be aware of the proper order. Only programmer/constructor knows is. Compiler should not take more responsibility and enforce the wrong order onto programmer.
Saying that I cannot initialize some fields because I did not ininialized the others is like "you cannot initialize the thing because it is not initialized". This is a kind of argument we have.
So, to conclude once more, the feature that "protects" me from doing things in simple and right way in order to enforce something that does not add noticeably to the bug elimination at that is a strongly negative thing and it pisses me off, altogether with the all the arguments to support it I've seen so far.
It is "a conceptual question about software development" Should there be the requirement to call super() first or not. I do not know. If you do or have an idea, you have place to answer. I think that I have provided enough arguments against this feature. Lets appreciate the ones who benefit form it. Let it just be something more than simple abstract and stupid "write your own language" or "protection" kind of argument. Why do we need it in the language that I am going to develop?