Why are member objects initialized after the superclass constructor?

Yesterday I ran into an interesting problem, and although the fix was pretty simple, I'm still a little blurry about the why.

I have a class that has a private member variable that is assigned when it is created, however, if it is used in an abstract function called by the superclass constructor, the variable does not matter. The solution to the problem was quite simple, I just 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 base class:

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

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

Since we are creating an object of type Foo, should its members not be allocated and assigned before calling its (and therefore its superclass) constructor? Is this indicated somewhere in the Java language or specifically the JVM?

Thank you for understanding!

+6
source share
2 answers

Purpose bar = "fooBar!"; built into the constructor at compile time.

The superclass constructor runs before the subclass constructor, so it would be natural for the statement to be executed later.

In general, it is bad practice to call overriden methods from the constructor.

+7
source

It is defined by the Java language specification. Changing it to static will almost never be an acceptable solution in a real situation.

See JLS 4.12.5 Initial Variable Values and JLS 8.3. 2 Field initialization

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

+1
source

Source: https://habr.com/ru/post/905875/


All Articles