简体   繁体   中英

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!

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.

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

Your code is breaking a golden rule in Java - never call a method in a constructor that can be overridden by a subclass - ie 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; .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM