Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are member objects initialized after the super class's constructor?

Tags:

java

I ran into an interesting problem yesterday and while the fix was quite simple, I'm still a bit fuzzy on the "why" of it.

I have a class that has a private member variable that is assigned when it is instantiated, however if it is used in an abstract function that is called by the super class's constructor, the variable does not have a value. The solution to the problem was quite simple, I simply had to declare the variable as static and it was assigned correctly. Some code to illustrate the problem:

class Foo extends BaseClass
{
    private final String bar = "fooBar!";
    public Foo()
    {
        super();
    }

    @Override 
    public void initialize()
    {
        System.out.println(bar);
    }
}

And the base class:

abstract class BaseClass
{
    public BaseClass()
    {
        initialize();
    }

    public abstract void initialize();
}

In this example, when we call new Foo(); it will output (null) instead of the expected fooBar!

Since we're instantiated an object of type Foo, should its members not be allocated and assigned prior to calling its (and consequently its super class's) constructor? Is this specified somewhere in the Java language or is it JVM specific?

Thanks for any insight!

like image 910
Matthew Williamson Avatar asked Jan 12 '12 23:01

Matthew Williamson


People also ask

Why we always initialize instance variables in a constructor?

A constructor is typically used to initialize instance variables representing the main properties of the created object. If we don't supply a constructor explicitly, the compiler will create a default constructor which has no arguments and just allocates memory for the object.

Why does Super have to be the first line in the constructor?

There's a way to get some code (other constructors) to run before the constructor really starts, before any members of the subclass are initialized. And that way is to put the "call" (eg super ) on the very first line.

Why do we initialize an object?

Variable initialization is important so that we do not accidently use a variable without assigning a value to it. Similarly Object initialization is important so that we do not accidently use an object before initializing the data members of the object.

Why creating an object of the subclass also invokes the constructor of the superclass?

Why creating an object of the sub class invokes also the constructor of the super class? When inheriting from another class, super() has to be called first in the constructor. If not, the compiler will insert that call. This is why super constructor is also invoked when a Sub object is created.


2 Answers

The assignment of bar = "fooBar!"; is inlined into the constructor during compile time.

The superclass constructor runs before the subclass constructor, hence it would only be natural that the statement is executed afterwards.

Generally though, it's bad practice to call overridable methods from a constructor.

like image 63
Johan Sjöberg Avatar answered Sep 23 '22 21:09

Johan Sjöberg


It is as defined by the Java Language Specification. Changing it to static will almost never be and acceptable solution in real world situation.

See JLS 4.12.5 Initial Values of Variablesand JLS 8.3.2 Initialization of Fields

Overall, it is bad practice to call a non-final method from a constructor. the reason being that it could (and if the method is abstract then definitely does) call method in the class that has not yet been initialized: When new Foo() is executed, the BaseClass initializer (constructor) gets called before the Foo constructor, so Foo.initialize is essentially working on an Object that has not been fully constructed yet.

like image 36
Miserable Variable Avatar answered Sep 20 '22 21:09

Miserable Variable