对象实例化过程
参考:
栈:基本数据类型和对象引用
堆:对象本身
方法区:存放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.
7.显示初始化
因为我们在定义Phone类时,对year和brand分别赋了初值,因此默认初始化之后,要进行第二次初始化 : 显式初始化。(如果类中没有对属性赋初值,没有这一步骤),如下图所示:
8.
9.
到这里new关键字的任务就算是完成了,当我们通过"对象." 的形式来调用时,实质就是通过引用pDemo指向的堆内存中对象的地址,进一步找到对象的成员变量或者成员方法。