I ended up the following scenario in code earlier today (which I admit is kinda weird and I have since refactored). When I ran my unit test I found that a field initialization was not set by the time that the superclass constructor has run. I realized that I do not fully understand the order of constructor / field initialization, so I am posting in the hopes that someone explain to me the order in which these occur.
class Foo extends FooBase {
String foo = "foobar";
@Override
public void setup() {
if (foo == null) {
throw new RuntimeException("foo is null");
}
super.setup();
}
}
class FooBase {
public FooBase() {
setup();
}
public void setup() {
}
}
@Test
public void testFoo() {
new Foo();
}
The abbreviated backtrace from JUnit is as follows, I guess I expected $Foo.<init> to set foo.
$Foo.setup
$FooBase.<init>
$Foo.<init>
.testFoo
In Java, the order for initialization statements is as follows: static variables and static initializers in order. instance variables and instance initializers in order. constructors.
Instantiation: The new keyword is a Java operator that creates the object. Initialization: The new operator is followed by a call to a constructor, which initializes the new object.
Order of constructor execution... ParentClass constructor executed. ChildClass constructor executed. In the above code, after creating an instance of ChildClass the ParentClass constructor is invoked first and then the ChildClass.
In Java, a constructor is a block of codes similar to the method. It is called when an instance of the class is created. At the time of calling constructor, memory for the object is allocated in the memory. It is a special type of method which is used to initialize the object.
Yes, in Java (unlike C#, for example) field initializers are called after the superclass constructor. Which means that any overridden method calls from the constructor will be called before the field initializers are executed.
The ordering is:
Basically, it's a bad idea to call non-final methods in constructors. If you're going to do so, document it very clearly so that anyone overriding the method knows that the method will be called before the field initializers (or constructor body) are executed.
See JLS section 12.5 for more details.
A constructor's first operation is always the invocation of the superclass constructor. Having no constructor explicitely defined in a class is equivalent to having
public Foo() {
super();
}
The constructor of the base class is thus called before any field of the subclass has been initialized. And your base class does something which should be avoided: call an overridable method.
Since this method is overridden in the subclass, it's invoked on an object that is not fully constructed yet, and thus sees the subclass field as null.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With