Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variable is null at super call

I'm using Java 7 and got 3 classes:

TestSuper.java

public abstract class TestSuper {
    public TestSuper() {
            testMethod();
    }

    protected abstract void testMethod();
}

TestNull.java

public class TestNull extends TestSuper {
    private String test = "Test";

    public TestNull() {
            super();
            System.out.println(test);
    }

    @Override
    protected void testMethod() {
            System.out.println(test);
    }

}

TestMain.java

public class TestMain {
    public static void main(String[] args) {
            new TestNull();
    }
}

Output:

null
Test

Why does this happen and is there a good workaround for it?

like image 959
Dennis Kriechel Avatar asked Jun 20 '14 12:06

Dennis Kriechel


People also ask

When super () is called?

2. Use of super with methods. This is used when we want to call the parent class method. So whenever a parent and child class have the same-named methods then to resolve ambiguity we use the super keyword.

Is super () called automatically?

Use of super() to access superclass constructor As we know, when an object of a class is created, its default constructor is automatically called. To explicitly call the superclass constructor from the subclass constructor, we use super() .

What is a null variable?

NULL is a special variable of type Undefined. Unlike a variable that is truly undefined, the value ! NULL can be assigned to other variables and used in comparisons.

What happens if super is not coded in Java?

Actually, nothing will be displayed. Since the class named Object is the superclass of all classes in Java. If you call "super()" without any superclass, Internally, the default constructor of the Object class will be invoked (which displays nothing).


3 Answers

When you call new TestNull(); you're calling the constructor of the class TestNull, which it calls the super() constructor: it contains a call to the method implemented in TestNull, where you print the String field, at this time the fields of the sub-class TestNull are not yet initialized, i.e. are null.

After the super constructor call, all the fields will be initialized, and therefore the second print actually show the new value of the (initialized) string.

The key point here is that fields of a sub-class are initialized after the instantiation of the super-classes.

A workaround? It depends on what exact behaviour you desire: maybe it makes sense to NOT call the abstract method in the super constructor (i.e. in the constructor of the TestSuper class).

like image 130
WoDoSc Avatar answered Oct 09 '22 17:10

WoDoSc


According to JLS 8.1.1.1 Abstract Class

A subclass of an abstract class that is not itself abstract may be instantiated, resulting in the execution of a constructor for the abstract class and, Therefore, the execution of the Field Initializers for instance variables of that class.

like image 31
akash Avatar answered Oct 09 '22 17:10

akash


You are calling an overridable instance method (which also calls an instance field, in your case private String test = "Test";) in the constructor. This might cause inconsistencies since the instance is not fully constructed. This is a bad practice, so avoid it:

public TestSuper() {
       testMethod();
}

Please read this thread: What's wrong with overridable method calls in constructors?

like image 1
Juvanis Avatar answered Oct 09 '22 18:10

Juvanis