java中,将内存划分为栈、堆和方法区三大块,在学习java时,理解程序运行时内存的变化有助于学习者更好的理解java中的概念,以及java中工具的使用。上篇文章中,简要介绍了对象创建时的内存图解。然而有时候,出于需要,会将创建的对象当作参数传给方法,为了更深刻的理解java中类与对象的概念,接下来介绍对象作为参数使用时的内存图解,顺便复习对象创建过程中的内存图解,以加深印象,方便理解。
首先创建一个学生类,要求将学生的姓名以及年龄设置为局部变量,并且定义方法打印学生类的对象正在努力学习。以下为这个学生类的实现代码:
package com.neicun.test;
/**
* 创建一个学生类,包含学生姓名以及学生年龄以及study()方法
*/
public class Student {
String name;
int age;
public void study(){
System.out.println(name+"正在努力学习");
}
}
然后定义一个测试类,要求创建Student类对象张三丰,年龄100,并调用study( )方法。随后创建一个shouwAge( Student s)方法,将Student类的对象作为形式参数传入方法,并使用。以下为代码示意:
package com.neicun.test;
/**
* 创建一个测试类
*/
public class TestStudent {
public static void main(String[] args) {
Student stu = new Student();//第1行代码
stu.name = "张三丰";//第2行代码
stu.age = 100;//第3行代码
stu.study();//第4行代码
showAge(stu);//第5行代码
}
public static void showAge(Student s){
System.out.println("学生"+s.name+"的年龄是"+s.age);
}
}
为方便表示,将main( )方法以下代码编号,将其分为5行。以下开始进行内存图解分析:
main( )方法作为程序的主入口,程序开始执行前,main( )方法存在的类会现在方法区加载字节码文件,然后在栈栈中开辟空间,这个空间叫main( )方法的栈帧。

第一行代码:代码执行时碰到Student类,由于一开始内存中没有 Student类,因此会先在方法区中加载Student的字节码文件。Student类中的study( )方法会在方法区中被赋予地址值,这里假设这个地址值为0x0066。随后会在main( )方法的栈帧中创造一个名为stu的Student类型的引用。
代码碰到new,随即向堆中申请开辟一个空间用来储存创建的对象信息。假设这个空间的地址为0x0011,随即将这个地址值传给stu。这个在堆中开辟的值会被分为三分,前两份用来储存创建对象的成员变量,此时成员变量的值为默认值。后一个用来储存成员方法的study()的地址值,这个地址值就是Student类字节码在方法区中加载时,方法区赋给study()方法的地址值。
第二、三行代码,根据stu提供的地址值,在堆内存中找到创建对象的地址,随后将值"张三丰"赋给成员变量name ,将值“100”赋值成员变量age。

第四行代码:根据stu提供的地址找到创建对象的地址值,然后在堆内存中找到成员方法处储存的地址值,根据地址值在方法区中找到study( )方法,随后执行study( )方法,study( )方法进栈,在栈中开辟栈帧,打印“张三丰正在努力学习”。方法结束,study( )方法退出栈空间。
在这个过程中,应该注意,study()方法并没有要求传入参数,而study()方法中,System.out.println(name+"正在努力学习");这行代码执行的结果为“张三丰正在努力学习”的原因为在java中使用变量遵循就近原则,即如果参数列表有,就使用,如果参数列表没有就去本类的成员位置找,有就使用,如果没有就去父类的成员位置找,有就使用,没有就报错。


第五行代码: 调用showAge( )方法,showAge( )方法进栈,在栈内存中开辟栈帧。随后执行showAge( )方法,传入值stu,此时应该注意,showAge( )方法传入的stu为自定义类Student的对象,而自定义类为引用类型,引用类型在作为参数传递时,它传递的是地址值。因此此处传递给showAge( )方法的是对象stu的地址值。也就是说showAge(Student s)方法中的s 和stu指向了相同的地址值。因此showAge(Student s )执行的结果为“学生张三丰的年龄是100”。

showAge( )方法结束后,showAge( )方法退出栈空间,main()方法结束,也退出了栈空间。程序结束,内存清空。

本文详细解释了Java中,当创建的对象作为参数传递给方法时,如何在栈、堆和方法区进行内存分配,以及如何处理引用类型的参数。通过实例展示了Student和TestStudent类的内存变化过程。
675

被折叠的 条评论
为什么被折叠?



