画图分析类实例化及操作时在内存中的变化及表现形式
package com.test;
public class Main {
public static void main(String[] args) {
//实例化一个Cat对象
Cat cat = new Cat();
//给成员变量赋值
cat.name = "招财";
cat.age = 2;
cat.weight = 2.02;
//打印
System.out.println("小猫的名字:"+cat.name + " 小猫的年龄:"+cat.age);
//调用成员方法
cat.say();
}
}
class Cat {
/**
* 成员变量 name
*/
String name;
/**
* 成员变量 age
*/
int age;
/**
* 成员变量 weight
*/
double weight;
public void say()
{
System.out.println("喵喵~~");
}
}
上面这段代码首先有个主程序的类 Main,这个我们不过多说明。我们主要分析 main 函数体里面的这段代码。
我们需要知道在 Cat 类中,定义了三个成员属性:name、age、weight;定义了一个成员方法:say ();
在 main () 函数里实例化对象 cat, 内存中在堆区内会给实例化对象 cat 分配一个内存地址,然后我们给对象 cat 进行了赋值并且打印了一些信息,最后调用了成员方法 say () ,程序执行完毕。
1. 在程序的执行过程中,首先 Main 类中的成员属性和成员方法会加载到方法区
2. 程序执行类 Main 的 main () 方法时,main () 函数方法体会进入栈区,这一过程叫做进栈 (压栈)。
3. 程序执行到 Cat cat = new Cat(); 时,首先会把 Cat 类的成员属性和成员方法加载到方法区,此时方法的内存空间地址为 1x000000,同时在在堆内存开辟一块内存空间 74a14482,用于存放 Cat 实例对象,并给成员属性及成员方法分配对应的地址空间,比如下图的 0x000001~0x000004 即为对象分配的堆内存地址,但此时成员属性都是默认值,比如 int 类型默认值为 0,String 类型默认值为 null,成员方法地址值为方法区对应成员方法体的内存地址值;然后在栈内存中会给变量 cat 分配一个栈地址 34b23231,用来存放 Cat 实例对象的引用地址的值 74a14482。
4. 接下来对 cat 对象进行赋值
//给成员变量赋值 cat.name = “招财”; cat.age = 2; cat.weight = 2.02;
先在栈区找到引用变量 cat,然后根据地址值找到 new Cat () 对象的内存地址,并对里面的属性进行赋值操作。由于成员属性 name 的类型为 String,为引用数据类型,所以此时会在常量池开辟一块地址空间 2x00000000,存放招财这个值,而 age 的类型为 int,weight 的类型为 double,都为基本数据类型,所以值直接存放堆中。
5. 当程序执行到 cat.say() ; 方法时,会先到栈区找到 cat 这个引用变量(这个变量存的是对象的引用地址),然后根据该地址值在堆内存中找到 new Cat () 对象里面的 say() 方法进行调用,在调用 say() 方法时,会在栈区开辟一块空间进行运行。
6. 在方法体 void say() 被调用完成后,就会立刻马上从栈内弹出(出站 ),最后,在 main () 函数完成后,main () 函数也会出栈
参考文档
本文为 joshua317 原创文章,转载请注明:转载自 joshua317 博客 https://www.joshua317.com/article/189