由一个简单示例 引出java继承中父子类成员变量共享问题 以及super的使用

由一个简单示例 引出java继承中父子类成员变量共享问题 以及super的使用_第1张图片


输出结果为

12

12

13

10



虚拟机执行步骤:

1:虚拟机加载测试类,提取类型信息到方法区。
2:通过保存在方法区的字节码,虚拟机开始执行main方法,main方法入栈。
3:执行main方法的第一条指令,new B(); 这句话就是给B类实例对象分配堆空间。因为B继承A父类,所以,虚拟机首先加载A类到方法区,并在堆中为父类成员变量在子类空间中初始化,这个过程中会创建A类的对象aa,包含A类中所有属性方法,包含int x, f(), hh(),然后加载B类到方法区,在堆中创建B类实例化对象bb,为bb的成员变量分配空间并初始化默认值,按照继承机制bb会继承A类所有成员变量和方法x, f(), hh(),bb对象中会开辟三个空间声明x, f(), hh()分别指向aa对象中的x, f(), hh()具体地址,同时额外开辟空间存储int y和g(),所以aa对象和bb对象的x, f(), hh()这三个属性方法是共享,但是aa和B类的x, f(), hh()并不共享,如果B类中x属性修改为String x;或者将方法f()修改实现重写(覆盖),那么子类对象bb中x或者f()不再和aa共享指向同一个引用,这时候bb会开辟空间存放x或者f()。
然后将B类的实例对象地址赋值给引用变量b。

4:之后虚拟机先后执行b.g() b.f() a.hh(),分别入栈出栈,最后程序回到main方法,main方法执行完毕出栈,主线程消亡,虚拟机实例消亡,程序结束。


下面解决几个问题:

1.为什么super.x输出是12?父类的x没有被修改啊?a.hh()的输出可以证明

答:B继承A的,创建B对象的时候会执行B的构造方法,图中B的构造方法未写出,自动调用无参构造,

public B(){

super();//自动调用A类构造方法

...

}

同时由于A中自动添加无参构造方法,也会对A的构造函数进行调用,创建隐含的A类对象aa,对象aa中为变量x分配了一个引用,aa和b都指向这个引用,x=x+2修改了引用里x的值,super.x也指向这个引用,所以输出的是修改后x的值,记住super.x指的是父类对象aa的x值 而不是父类的x值 所以super.x表示aa对象的x值 该值和bb的x值指向同一个引用。过程中创建的变量x、函数f()、hh()的引用同时给了父类和子类创建的对象,f()函数修改了x的值,即aa对象和bb对象指向的x修改了。。总的来说,super.x和bb.x是指向同一块内存地址的。

2.如果在Class B中添加int X,结果会是如何?

答:在原题中B类里面根本就没有定义 X, 所以你引用的也是父类的 那么当X=X+2的时候改变的也是父类对象的X 如果B类中 声明一个int X那么X变量被重写(覆盖),那么子类对象中对x的操作只会引起bb中x的值,父类对象aa中的X就不会是12 ,而是10。此时子类中的X变量和父类的X不存在引用关系。



3.为什么A a=new A();

a.hh()打印的是10 而不是13

答:之前对x的操作只改变了aa和bb中共享的x值,对类没有影响,new出一个新对象是按照类进行初始化的,所以x的初始值还是10


另外:类是一个抽象的概念,对象才是具体的,子类的动作只会影响到父类的对象,你父类的属性是不受影响的。


如都不是private 那么子类将覆盖父类field 子类中出现两个field 默认的是子类.field 访问父类field通过super.field




java中子类对父类属性方法的继承或者覆盖分类:

个人总结大致5种情况:

父子都有 父有子无 父无子有
1.最普通 父类有非private的field子类无field 直接继承 指向相同存储空间 this.field和super.field指向同一
2. 父类有field 但是private 子类无field 直接继承 但是field隐藏在子类不可见 无法访问子类field 理解为子类不存在field
3.父子都有field 父类field属性非pirvate 经典覆盖(重写) 无法继承父类field 默认用自己的 子类中有两个field空间  this.field和super.field分别执行子类field和父类field
4.父子都有field 但是父类pirvate 子类有父类private修饰的field变量 但是父类field不可见 只有自己的field可见  无法继承 无法重写  super.field出错 类似于第5种  子类中field纯属额外属性 
5.父无field 子有field 额外附加属性方法




你可能感兴趣的:(由一个简单示例 引出java继承中父子类成员变量共享问题 以及super的使用)