Java 继承 父类变量, 方法 与子类的关系:

----------个人见解,如有不对之处,还请各路高人、老鸟给予指正:

知识基础: 变量和方法在jvm中的存储:

a).静态变量:存储在jvm的栈中,整个jvm只此一份。

b).成员变量: 存储在jvm的堆中,每个实例都有一份。

c). 方法:存储在jvm的栈中,整个jvm中也是只此一份。

 先提出几个问题(java继承方面的):

1.在一个父类被多个子类继承时,这些子类所访问的父类成员变量是同一个吗?

2.在问题 1  的基础上,如果父类是个抽象类呢,会是怎样?

3.在问题1和2的基础上,如果子类通过父类的某个方法,访问父类的某个私有的成员变量,会是怎样?

4.在一个父类被多个子类继承时,子类继承到的父类成员变量在jvm中的存储是怎样的?


第一个问题:

测试环境:

类Z:

public class Z {

int i=2;
}


类A:

public class A {
Z z = new Z();

public void printI(){
System.out.println("A:"+ z.hashCode());
}
}

B:

public class B extends A{

public B(){

}

public void printIi(){
System.out.println("B:"+ z.hashCode());
}
}

类C:

public class C extends A{

public void printIi(){
System.out.println("C:"+ z.hashCode());
}
}


测试类Test:

public class Test {


public static void main(String[] args) {
A a = new A();
B b =new B();
C c=new C();

a.printI();
b.printI();
c.printI();

a.printI();
b.printIi();
c.printIi();
}
}

运行结果:

A:903470137
A:1913208269
A:1018730552


A:903470137
B:1913208269
C:1018730552

答案显而易见,所返回的并不是同一个变量。也就是说,在初始化子类时,父类会首先得到初始化。其实这里的“父类会首先得到初始化”有更深的理解:在初始化父类的时候,会把父类所有的成员变量进行初始化(static变量除外,因为早在类加载的时候静态变量已被初始化了),在jvm中会为父类划出一块内存区域来存放这些变量,并将这些变量的引用给了当前初始化的子类,而此时父类的方法块,还是原来的同一个方法块。因此,当一个父类被多个子类继承时,该父类的成员变量就会被初始化多个副本,且这些副本的引用分配给了相应的子类。


第二个问题:测试环境:

B,C,Z类代码不变。

A类:

public abstract class A {
Z z = new Z();

public void printI(){
System.out.println("A:"+ z.hashCode());
}
}

测试类Test:



public class Test {
public static void main(String[] args) {
// A a = new A();
B b =new B();
C c=new C();

// a.printI();
b.printI();
c.printI();

// a.printI();
b.printIi();
c.printIi();
}
}

运行结果:

A:903470137
A:1913208269

B:903470137
C:1913208269

答案:不是同一个变量,原理同第一个问题。


第3个问题:

测试环境:

Z类不变。

A类:

public abstract class A {
private Z z = new Z();

public void printI(){
System.out.println("A:"+ z.hashCode());
}
}

B类:

public class B extends A{

}

C类:

public class C extends A{

}

测试类Test:

public class Test {


public static void main(String[] args) {
B b =new B();
C c=new C();

b.printI();
c.printI();

}
}

在测试类中b,c调用的都是父类中的printI();


运行结果:

A:903470137
A:1913208269
答案
:不是同一个变量。尽管此时父类中的成员变量z是私有的,子类无法直接调用。但是从结果上来看,通过测试程序的这种条用方法,所调用的z对象仍然不是同一个对象。也就说明了:在初始化父类的时候,父类的私有变量也会被初始化,只不过子类无法直接调用而已。


第4个问题:

在jvm中会为父类划出一块内存区域来存放这些变量,并将这些变量的引用给了当前初始化的子类,而此时父类的方法块,还是原来的同一个方法块。因此,当一个父类被多个子类继承时,该父类的成员变量就会被初始化多个副本,且这些副本的引用分配给了相应的子类。


以上内容如有不对的地方,还请指出,以便改正,多谢!

原创:转载请说明出处。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值