对象实例化过程

参考: https://blog.csdn.net/danielxinhj/article/details/127455571

 

栈:基本数据类型和对象引用

堆:对象本身

方法区:存放class的所有属性和Static 属性,线程共享

public  class  Phone {
    public String brand ="小米";
    public int  year =1;
    getset 方法
    有参,无参构造
}
public  class  TestPhone {
    public static void main(String[] args) { 
  Phone pDemo
= new Phone(2,"huawei");
  System.out.println(pDemo.getBrand());
   System.out.println(pDemo.getYear());
}
}

 1.main方法是程序的入口,执行main方法,main进入到方法区中

对象实例化

2.main方法进栈,并在栈中定义了一个用于指向 Phone实例的变量 pDemo

对象实例化

3.执行 main方法里面的代码 ,Phone pDemo = new Phone(2,"huawei"); ,从右向左执行,首先便遇到了new关键字,因为new关键字后面出现了Phone类,表示要实例化的是Phone类,而Phone类的字节码文件还没有加载到方法区,jvm不认识Phone,因此下一步是将Phone类的字节码文件加载到方法区(假设Phone类成员方法在方法区中的地址值为0x0088)

对象实例化

4.进行new 操作

Phone类的字节码文件加载到方法区之后,new关键字会在堆内存开辟空间给新的Phone类对象,假设Phone类对象在内存中的地址值为0x0011。如下图所示 :

对象实例化

5.堆中开辟空间赋值

根据Phone类的字节码文件,在堆中分配的这块内存空间会被分成三部分,分别是属性值year,brand,和Phone类的成员方法,Phone类的成员方法部分其实是成员方法在方法区中的地址值,将来如果对象调用成员方法,可以通过这个地址值找到方法区中的成员方法。如下图所示 :

对象实例化

6.默认初始化 

对对象的属性值进行第一次初始化 : 默认初始化。对应于Phone类中,year是int类型默认值0;brand是String类型默认值null,如下图 :

对象实例化

7.显示初始化

因为我们在定义Phone类时,对year和brand分别赋了初值,因此默认初始化之后,要进行第二次初始化 : 显式初始化。(如果类中没有对属性赋初值,没有这一步骤),如下图所示:

对象实例化

8.构造器初始化

创建一个对象,需要构造器来进行构造器初始化,因为我们调用的是Phone类的带参构造,因此要进行第三次初始化 : 构造器初始化。即将属性值更改为调用带参构造时传入的形参。

对象实例化

9.常量池

这里的字符串常量"Huawei",在常量池中,也有自己的地址,调用模式类似于成员方法。brand属性这里其实保存的是"Huawei"在常量池中的地址值,如下图所示 :

对象实例化

10.new关键字结束

最后,把对象的地址值返回给pDemo引用就可以了,如下图所示 :

对象实例化

 

到这里new关键字的任务就算是完成了,当我们通过"对象." 的形式来调用时,实质就是通过引用pDemo指向的堆内存中对象的地址,进一步找到对象的成员变量或者成员方法。

posted @ 2023-01-13 00:47  早日月薪五万  阅读(36)  评论(0编辑  收藏  举报