Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
279 views
in Technique[技术] by (71.8m points)

java - Initialization in polymorphism of variables

Suppose you have the following code

class A {
    int i = 4;

    A() { 
        print();
    }

    void print () {
        System.out.println("A");
    }
}

class B extends A {
    int i = 2;              //"this line"

    public static void main(String[] args){
        A a = new B();
        a.print();
    }

    void print () {
        System.out.println(i);
    }
}

this will print 0 2

Now, if you remove line labeled "this line" the code will print 4 4

  • I understand that if there was no int i=2; line,

A a = new B(); will call class A, initializes i as 4, call constructor,
which gives control over to print() method in class B, and finally prints 4.

a.print() will call print() method in class B because the methods will bind at runtime, which will also use the value defined at class A, 4.

(Of course if there is any mistake in my reasoning, let me know)

  • However, what i don't understand is if there is int i=2.

why is it that if you insert the code, the first part (creating object) will all of sudden print 0 instead of 4? Why does it not initialize the variable as i=4, but instead assigns default value?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It is a combination of several behaviors in Java.

  1. Method overriding
  2. Instance variable shadowing
  3. order of constructors

I will simply go through what happened in your code, and see if you understand.

Your code conceptually looks like this (skipping main()):

class A {
    int i = 0; // default value

    A() { 
        A::i = 4;  // originally in initialization statement
        print();
    }

    void print () {
        System.out.println("A");
    }
}

class B extends A {
    int i = 0;              // Remember this shadows A::i

    public B() {
        super();
        B::i = 2;
    }

    void print () {
        System.out.println(i);
    }
}

So, when in your original main(), you called A a = new B();, it is constructing a B, for which this happens:

  • A::i and B::i are all in default value 0
  • super(), which means A's constructor is called
    • A::i is set to 4
    • print() is called. Due to late-binding, it is bound to B::print()
    • B::print() is trying to print out B::i, which which is still 0
  • B::i is set to 2

Then when you call a.print() in your main(), it is bounded to B::print() which is printing out B::i (which is 2 at this moment).

Hence the result you see


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...