我们先放一段代码,然后根据这两段代码,来看有关于对象的内存。
public class Demo02Phone { // 成员变量 String brand; // 品牌 double price; // 价格 String color; // 颜色 // 成员方法 public void call(String who) {// 打电话 System.out.println("给" + who + "打电话"); } public void text() {// 群发短信 System.out.println("群发短信"); } }
public class Demo02Phone2 { public static void main(String[] args) { Demo02Phone phone = new Demo02Phone(); System.out.println(phone.brand);// 品牌 System.out.println(phone.color);// 颜色 System.out.println(phone.price);// 价格 System.out.println("------------------"); phone.brand = "华为"; phone.color = "玫瑰金"; phone.price = 2000.0 ; System.out.println(phone.brand);// 品牌 System.out.println(phone.color);// 颜色 System.out.println(phone.price);// 价格 System.out.println("------------------"); phone.call("易烊千玺"); phone.text(); } }
首先方法区存放着.class相关信息,包括类中方法的死信息,而方法如main方法想要运行必须进栈(压栈),方法中的局部变量,在栈中,声明的变量如果是new了,那么就在堆中。
此处注意,相当于new出来的对象,在堆里开辟了一块内存空间生成一个地址,然后这个对象从方法区.class读取成员变量和成员方法的信息,有关成员变量的信息仅仅是参考着方法区的成员变量,在队里创建同样的变量(这些变量到时候是从栈里直接根据堆为new出来的对象生成的地址来进行查找),放进堆里并为其赋默认值,而有关于成员方法,注意注意!!存储的是该方法在方法区的地址值!
栈中存储着方法中的局部变量,为其赋值时赋new出来的对象的话,就是把这个对象在堆里的地址值赋值给它。
而存储着对象的成员变量时,给它赋值后,首先是根据它的对象名,在栈里找到同名的局部变量(对象)根据它的赋值(new的对象的地址值)找到堆里new出来的对象存储的内容,找到里面同名的成员变量对其当前的默认值进行修改,放上重新赋的值。
而在栈中访问成员变量时,首先根据它的对象名,在栈里找到同名的局部变量(对象)根据它的赋值(new的对象的地址值)找到堆里new出来的对象存储的内容,找到里面同名的成员方法,找到其赋值的方法区的地址,按地址到方法区同名方法,但注意,该方法想要运行,还是要进栈的,如同main方法。
歪题tips:进栈为什么也叫压栈,因为先来的方法在低下,后来的在上面。
那么下一步,带着自己的参数同样在栈中找到这个同名方法,进行运行。
注意:运行后,该方法就出栈(弹栈)!从栈内存中消失!