前言
上篇文章给大家带来了继承的特性以及面向对象中继承带来的优缺点,能够深入理解这些特性,对OOP设计也有的新的认识,在JDK中绝大多数都是通过继承来扩展代码提高复用性,也为今后的学习打下了坚实的基础。
本篇内容给大家讲解继承在JVM虚拟机中内存的分布和动态变化,从对象的创建初始化再到对象的销毁过程,如果能够深入理解此篇内容,无疑这对你今后的提升有着很大的帮助!
继承JVM内存布局
首先编写一个伪代码,通过代码来进行研究。 编写三个类,分别为A、B、C,让他们依次继承,A为最高基类。在main方法中new 一个C类对象。如下:
public class ExtendsTheory {
public static void main(String[] args) {
C c = new C();
}
}
class A{
String name="A类";
int num=1;
}
class B extends A{
String name="B类";
int num=2;
}
class C extends B{
String name="C类";
int num=3;
}
当然光看这些代码我们会觉得很容易,这次我们要研究的是JVM模型内存分布。通过之前所学我们知道当创建子类对象时,会往上寻找父类对象直到Object,然后开始依次加载。由此我们可以得出:
- 当在main方法中C c = new C()时,首先会在方法区中开辟空间进行类加载,加载该类以及父类的属性和方法。
- 在堆中开辟一块new C()的地址,从最高父类开始依次加载类信息,并进行初始化,基本数据类型会直接存放到该空间,引用数据类型则在该空间存放地址,具体信息存到常量池中。
- 此时栈中对象的引用c指向堆中的地址。
大致分布图如下:
从中可以清晰的看出,会依次向上找父类,向下进行加载。
思考
当我们c.name会返回谁的信息?在B类中添加一个属性还能通过对象c访问到吗?
public class ExtendsTheory {
public static void main(String[] args) {
C c = new C(); //创建C类对象
System.out.println(c.name);
System.out.println(c.flag);
}
}
class A{
String name="A类";
int num=1;
}
class B extends A{
String name="B类";
int num=2;
int flag=1;
}
class C extends B{
String name="C类";
int num=3;
}
控制台打印:
C类
1
根据打印结果可以得知:
- 首先会该看本类对象是否有该属性,如果本类中有该属性,并且可以访问到(非private),则返回该信息。如果属性被private修饰时,访问该属性会报错。
- 当子类没有该属性,会向上找父类中的属性,直到找到为止并返回信息。如果直到Object都没有该属性会直接报错。
本篇内容主要讲了java面向对象继承在JVM中的内存分布。到目前为止面向对象继承这一小结就结束了,熟悉掌握为今后打下坚实的基础!