Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Calling superclass' constructor which calls overridden method which sets a field of subclass

I have this demo code:

class Test2 extends Test {
    public int number = 0;

    @Override
    public void set(){
        number = 1;
        info();
    }

    @Override
    public void info(){
        System.out.println(number);
    }
}

public class Test {
    public Test(){
        set();
    }

    public void set(){
    }

    public void info(){
    }

    public static void main(String[] args){
        Test2 object = new Test2();
        object.info();
    }
}

The code gives this output:

1
0

Why? I expect this output:

1
1

In my opionion, the main function calls a constructor of Test2 class to create an object. The constructor calls automatically superclass' constructor. This constructor calls method set() which is overridden. Therefore method set() of class Test2 is called. This method sets the field and calls info() method which writes the number. Then the main function calls the info() method of the created object again.

The number field is correctly set as the first line output is "1". But why the second line contains 0? It seems that the field was not set at all. Can you explain it?

What should I do to get the behaviour I expect? Thanks in advance!

like image 852
user1608790 Avatar asked Aug 23 '12 21:08

user1608790


3 Answers

class Test2 {
    public int number = 0;
}

is equivalent to

class Test2 {
    public int number;

    public Test2() {
        super();
        number = 0;
    }
}

So through invoking the super constructor the field number is set to 1. After the return from the super constructor, your assignment of number to 0 is executed.

Just remove the assignment and it should behave as you expect.

like image 81
xehpuk Avatar answered Nov 18 '22 21:11

xehpuk


If say Animal extends Dog and you call Animal a = new Dog()

Then sequence of steps would be as below

  1. Static Fields of Animal are initialized

  2. Static Block of Animal is executed

  3. Static Fields of Dog are Initialized < They would be reinitialized if Animal changed them in anyway>

  4. Static Block Of Dog is executed

  5. Non Static Field Of Animal are Initialized They would be reinitialized if Animal changed them in anyway>

  6. Animal Constructor is executed

  7. Non Static Field Of Dog Initialized < They would be reinitialized if Animal changed them >

  8. Dog Constructor is execued

like image 25
check Avatar answered Nov 18 '22 21:11

check


Your code is breaking a golden rule in Java - never call a method in a constructor that can be overridden by a subclass - i.e. such methods should be private.

By the time the default constructor in Test2 completes, it has overwritten the initial value of 1 assigned to it via the initializer public int number = 0;.

like image 33
JamesB Avatar answered Nov 18 '22 21:11

JamesB