今天给大家分享在Java中创建对象的内存机制
程序在计算机中运行的时候会被先加载到内存,而一个程序在内存中的存放一般有如下划分
1、栈是用来存放局部变量和参与函数调用
2、堆是用来存储对象,一般new出来的都存放在堆中
3、方法区(图中未给出)用来加载类
下面定义一个Car类:
在这里插入代码片package demo01;
public class Car {
String name;
double price;
public void start(){
System.out.println(name + "启动了");
}
public void run(){
System.out.println(name+"正在行驶");
}
}
下面再定义一个测试类:
package demo01;
public class Test {
public static void main(String[] args) {
Car c1 = new Car();
c1.name = "奔驰";
c1.price = 39.78;
System.out.println(c1.name);
System.out.println(c1.price);
c1.start();
c1.run();
Car c2 = new Car();
c2.name = "奥迪";
c2.price = 38.90;
System.out.println(c2.name);
System.out.println(c2.price);
c2.start();
c2.run();
System.out.println(c1);
System.out.println(c2);
}
}
在这里插入代码片
我们在Car类中定义了Car类的两个属性和两个方法,分别是name和price属性,start和run方法。在测试类Test中分别创建了两个对象c1和c2。
编译器执行时,首先将Test.class加载到方法区,之后Test类中首先执行main方法,此时虚拟机将main方法调入栈内存,然后执行第一行代码Car c1 = new Car();
这时,会触碰Car类,所以编译器将Car.class加载到方法区。这行代码左边定义了一个Car类的变量c1,所以会在栈内存中开辟一个空间用于存放变量c1,代码的等号右边执行new,会在堆内存中开辟一块空间用于存放对象c1,属于对象c1d的空间内还会再次划分空间,用于存放属性和方法的引用地址(这里为什么是引用地址?因为方法一般代码可能较多,如果全存在对象中,会极大地占据堆内存的空间,所以这里存放一个引用地址,当调用方法时,根据地址去方法区寻找方法)。接下来,系统会将对象所在内存空间的地址赋给c1,用于指向对象。(如果在程序中通过输出语句直接输出c1与c2会得到两个地址值)
当执行到第二行和第三行代码c1.name = "奔驰"; c1.price = 39.78;
时,c1的两个属性值会改变为“奔驰和39.78”。
执行第四、五两行代码System.out.println(c1.name); System.out.println(c1.price);
时,输出c1.name
和c1.price,
即c1变量指向的对象中的name和price的值。
执行第六、七行代码时,首先会通过c1中的地址找到c1对象,在对象中通过成员方法引用地址找到方法,调到栈内存中进行执行,上述图中空间有限没有给出start和run方法的调用示意图。
创建c2对象过程与创建c1相同。
下一节,我们将叙述两个变量指向同一个对象的内存机制。
谢谢阅读!
如有疑问,可评论交流!