Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is object field initialization and constructor order in Java

Tags:

java

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
like image 967
Ransom Briggs Avatar asked Dec 13 '13 22:12

Ransom Briggs


People also ask

What is initialization order in Java?

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.

What is object initialization in Java?

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.

What is the order of constructor execution in Java?

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.

How does a constructor initialize an object in Java?

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.


2 Answers

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:

  • Initialize superclass (recursively invoke these steps)
  • Execute field initializers
  • Execute constructor body (after any constructor chaining, which has already taken place in step 1)

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.

like image 189
Jon Skeet Avatar answered Nov 05 '22 02:11

Jon Skeet


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.

like image 24
JB Nizet Avatar answered Nov 05 '22 03:11

JB Nizet