Java -- 父类和子类拥有同名变量

Java – 父类和子类拥有同名变量

                      请仔细观察系列两段程序的不同之处:一个Son类重写print方法,另一个则没有重写。

分析该问题必须从字节码的角度入手,否则根本不可能看清事情的本质。

成员变量(非静态的)的赋值过程:

  1. 默认初始化
  2. 显示初始化 / 代码块中初始化
  3. 构造器中初始化
  4. 有了对象之后。可以“对象.属性”或“对象.方法”的方式队成员变量进行赋值。

                                    最重要的是要搞清楚父类和子类的同名变量是否占用一块内存!!!

方法存在重载,但属性不存在重载。
package test0;

/**
 * @author wsh2096
 * @create 2020-10-28 8:57
 */
public class SonTest {
    public static void main(String[] args) {
        Father f = new Son();
        System.out.println(f.x);
    }
}

class Father {

    int x = 10;

    public Father() {
        this.print();
        x = 20;
    }

    public void print() {
        System.out.println("Father.x = " + x);
    }
}

class Son extends Father {

    int x = 30;

    public Son() {
        this.print();
        x = 40;
    }

    @Override
    public void print() {
        System.out.println("Son.x = " + x);
    }
}

在这里插入图片描述
Father类的字节码:
       init方法字节码:
Java -- 父类和子类拥有同名变量_第1张图片
       print方法字节码
Java -- 父类和子类拥有同名变量_第2张图片

Son类的字节码:
       init方法字节码:
Java -- 父类和子类拥有同名变量_第3张图片
       print方法字节码
Java -- 父类和子类拥有同名变量_第4张图片

分析:
        第一个输出0的原因是:在调用print方法的时候,子类Son重载该方法,所以调用子类方法进行输出,此时子类的x还没有显示初始化,所以输出的是子类x默认初始化值0。

        第二个输出30的原因是:在Son类的构造器进行输出,此时Son类的x已经进行完显示初始化,将Son的x值赋值为30.

        第三个输出20的原因是:此时变量f实际上指向的是Son类的实例,但是外观上是Father类,由于方法存在重载,会进行动态链接进行查找子类的具体实现方法!但是,属性十不存在重载,也就不存在动态链接,所以此时输出f的x值,是去查找Father类实例的属性x的值。(此时父类的构造器已经执行完毕,所以此时的值为20.)


                                                               对父类的print方法不进行重载!

package test0;

/**
 * @author wsh2096
 * @create 2020-10-28 8:57
 */
public class SonTest {
    public static void main(String[] args) {
        Father f = new Son();
        System.out.println(f.x);
    }
}

class Father {

    int x = 10;

    public Father() {
        this.print();
        x = 20;
    }

    public void print() {
        System.out.println("Father.x = " + x);
    }
}

class Son extends Father {

    int x = 30;

    public Son() {
        this.print();
        x = 40;
    }

//    @Override
//    public void print() {
//        System.out.println("Son.x = " + x);
//    }
}

在这里插入图片描述
       这个没有重载print方法的版本就不放字节码了,与重载的版本相比,只不过是少了东西,其他部分都是一样的。


       最后一个输出不需要解释!
       第一个输出10,是因为子类并没有重载print方法,所以调用Father的print方法,输出的就是父类的x值,此时已经完成显示初始化,为10.
       第二个输出20,属性不能重载,输出Father的x值,此时完成Father构造器初始化,将值赋为20.

你可能感兴趣的:(Java,#,杂谈,Java,继承,同名变量,重载)