话不多说,直接开干
public class Persion implements Serializable {
private Integer age;
private String name;
private String sex;
private String address;
//省略set/get方法
}
public class My_Main {
public static void main(String[] args) {
Persion p=new Persion();// 1_2
}
}
Notice:在这里,我们假设Persion类的编译已经完成,对于.Class文件的生成和内部结构在本篇文章中不会做过多的说明。
接下来,我们将从1_2开始谈起。对于本行的代码,从左往右阅读总共会被分为两个部分:
- Persion p:这个部分将会具体反映到java栈的本地变量中,作为一个引用数据类型出现。(在这里我们称之为引用类型变量p)
- new Persion():这个部分将会反应到java的堆中形成一块存储了Persion类型所有实例数据的结构化内存。(称之为Persion实例)
补充:我们知道,在jvm的内存结构中栈和堆是两块不同的数据块区域,在这种情况下,在1中定义的引用变量p是怎样和堆中Persion实例相关联的呢?
在java的虚拟机中有两种主流的实现方式(以下图片来源于《深入理解java虚拟机》):
- 使用句柄
- 直接指针
针对两种访问方式分别分析他们的优缺点:
- 1.句柄方式:
优点:因为句柄池的存在,所以实际的p中保存的句柄地址,在对象被移动的时候只需要改变句柄池中的内容,而无需改变p的值。 - 2.指针方式:
优点:因为是直接访问,所以相对来说速度更块。
相信看到这里,相信读者有了一个大概的了解。在上面的内容中,我们提到了 栈、方法区、堆 等几个概念,他们究竟是什么?有什么联系?与类对象的初始化又有什么关系?接下来,我们一起探讨。