基于内存模型图的Java 传值与传引用教学研究
2024-11-29魏宾宾李馨怡王娜龙凯鑫
摘要:在职业教育的课堂上,Java语言的教学更多地偏向代码的练习,由于Java虚拟机的说明文档晦涩难懂,不方便引入Java虚拟机相关内容,不利于学生理解程序。文章提出通过内存模型图的方法帮助学生理解和学习Java语言,并以传值和传引用为例进行了实证研究。
关键词:职业院校课堂教学;Java语言堂教学;内存模型图应用
中图分类号:G424 文献标识码:A
文章编号:1009-3044(2024)27-0152-03
0 引言
在高职院校软件相关的课程体系中,语言的教学大多从Java语言开始,Java语言虽然只是一门语言,但其有严谨的支撑体系,Java虚拟机。Java语言的学习从更多的是从使用角度切入学习,如果不能理解Java虚拟机,对学生的语言掌握程度会有部分影响。针对这个问题,宋平、王振建议学生反复揣摩、修改和尝试[1]。职业院校的课程设计更多的是对接产业链和企业技能需求,并没有完善的学科支撑体系。在没有学过电路和计算机组成原理的学科体系相关的课程,学生在面临理解Java语言,尤其是Java语言中的面向对象部分,理解较为困难。针对此问题张大鹏提出了将内存模型引入课堂,文献中得出的结论是:引入内存模型进入课堂教学可以使学生理解更加深刻,降低了程序的抽象程度[2]。本人在课堂实践中发现即使将内存模型融入课堂教学,对学生来说让人比较难以理解,通过结合程序画内存模型图的方式可以比较有效地帮助学生理解Java语言。曾荣在C语言教学难点探索时,将内存单元画出来,结合内存单元图来讲解C 语言中的难点也是一种比较好的参考[3]。综上所述画好内存模型图有助于同学更好地理解和学习Java 语言。
1 Java 内存模型概述
惠华先总结了Java虚拟机内存区域相关的内容。Java虚拟机的内存区域主要包含:方法区、堆、Java栈、PC寄存器和本地方法栈等5个区域[4]。
方法区主要包含:类型信息、常量池、字段信息、方法信息、类变量、一个指向ClassLoader的引用、一个指向class 的引用、一个指向class 对象的引用、方法表;堆中主要存储句柄池和对象池、每个包含一个指向特殊数据结构的指针;Java栈中主要由3部分组成:局部变量表、操作数栈和帧数据区;PC寄存器用于保存机器的运行状态;本地方法栈是指Java虚拟机用到的与本地方法相关的数据区。
内存模型主要基于现有的计算机内存结构,现有的计算机内存类似一个指定长度的数组,数组下标类似一个内存地址。传值和传引用案例研究时,重点关注:程序调用栈中存储的程序执行到那一行;局部变量表中存储的8种基本数据类型和引用数据类型;堆区中会使用连续的内存空间,存储创建出来的对象信息;方法区中存储的方法表、方法的信息和字符串常量池。
程序调用栈的内存模型图画法:程序调用栈是一个栈型的结构,主要存储程序执行到那一行,在执行函数调用时,程序调用栈会发生入栈操作,如图1所示。
当栈底上面一行存储的行号所在的函数执行结束后,会发生出栈操作。之后程序会执行栈底所在函数行号的下一行,直到Main函数执行结束,整个程序调用栈销毁。
局部变量表的画法:局部变量表中存储的主要是8种基本数据类型和引用数据类型,可以使用连续的内存空间来存储具体的数据类型,如图2所示。
堆区的画法:堆区主要存储的是对象的信息,对象主要包含成员变量,方法表的引用等信息,如图3 所示。
方法区的画法:方法区主要存储的是方法表(某个对象的各个方法引用),方法的实现,字符串常量池等信息,如图4所示。
2 内存模型在教学中的应用
在方法调用中,参数可以通过值传递或引用传递来传递给方法。值传递是一种将参数的值复制到方法中的过程。这种传递方式适用于简单数据类型,如整数、浮点数和布尔值等。常用的值传递对应的数据类型在Java中指的是8种基本数据类型:byte、short、int、long、float、double、char、boolean。
Java传值的过程中,将某个变量传递给函数,此变量在函数的作用域中可能会发生各种变化。当函数执行结束之后,外部调用方再次使用传入方的那个变量,此变量的值依旧是传入函数之前的那个值。
Java中的引用数据类型:
类:class
接口:interface
数组:array
引用数据类型就是指内存空间可以同时被多个栈内存引用。接下来通过一个案例分析对象的引用传递。
3 传引用的案例分析
传引用的程序代码[5]如下:
1 class Student {
2 String name; // 声明姓名属性
3 int age; // 声明年龄属性
4 void read() {
5 System.out.println("大家好,我是"+name+",年龄"+age);
6 }
7 }
8 class Example02 {
9 public static void main(String[] args) {
10 Student stu1 = new Student (); //声明stu1 对象并实例化
11 Student stu2 = null; //声明stu2对象,初始值为null
12 stu2 = stu1; //将stu1的内存地址赋值给stu2
13 stu1.name = "小明"; //为stu1对象的name 属性赋值
14 stu1.age = 20; //为stu2对象的age属性赋值
15 stu2.age = 50;
16 stu1.read(); //调用stu1的方法
17 stu2.read();
18 }
19 } 程序执行结果如下:
大家好,我是小明,年龄50。
大家好,我是小明,年龄50。
4 传引用案例的内存模型图分析
第10 行代码Student stu1 = new Student ();声明stu1对象并实例化,程序在执行new关键字代码之后,会在内存中创建new关键字后对应的对象。程序调用栈中存储的是程序执行到那一行,当前是第10行。局部变量表中存储当前程序可以使用的对象的引用,是stu1。堆区中存储的是当前可以使用的对象的资源,包括成员变量name和age,初始值Kuf0RP7JuSCUgF3r1kaRgmeCmSFqloJHN7JJYmMWCUo=分别是null和0,还有一个指向方法表的引用。方法区中主要存储的是方法表包含read方法和read方法的实现。通过内存模型图将第10行代码执行后的内存状态表现出来,如图5所示。
第11行代码Student stu2 = null; 声明stu2对象,但不对其进行实例化,没有实例化的对象的默认初始值为null。通过内存模型图将第11行代码执行后的内存状态表现出来,如图6所示。
第12行代码stu2 = stu1; 把stu1对象的引用赋值给stu2,此时stu1和stu2指向同一个的内存地址。通过内存模型图将第12行代码执行后的内存状态表现出来,如图7所示。
第13 行代码stu1.name = "小明";为stu1 对象的name属性赋值。“小明”是一个非new关键字创建出来的字符串,存储在Java虚拟机的字符串常量池中。字符串常量池也是方法区的一部分。通过内存模型图将第13行代码执行后的内存状态表现出来,如图8 所示。
第14行stu1.age = 20; 为stu1对象的age 属性赋值,使age的值变为20。通过内存模型图将第14行代码执行后的内存状态表现出来,如图9所示。
第15行stu2.age = 50; 为stu2对象的age 属性赋值。赋值之后age的值变为50。通过内存模型图将第15行代码执行后的内存状态表现出来,如图10所示。
分析:stu1和stu2指向的是同一内存地址,所以修改堆区的数据stu1和stu2都可以访问到,最终stu1和stu2的属性值相同,程序输出的结果也相同。
5 总结
内存模型图是一种帮助理解程序的好方法。同学们通过对内存模型的分析,可以比较清楚分析面向对象程序在内存中的变化状态,更加准确地理解程序。但同时也会面临如下问题:首先内存模型图有助于帮助同学理解程序,并不能完全准确地模拟程序在内存中的变化状态;其次本例中的在画内存模型图时,会使用局部变量表、程序调用栈、堆区、方法区和字符串常量池等概念,也会部分增加学生的理解难度。综上所述在教学实践中有利于同学理解Java中的传值和传引用,借助内存模型图来教学是一种比较好的教学方法。
本文重点是传值和传引用的研究案例,由于在Java语言教学中,有较多的学习内容比较靠近Java虚拟机,这部分内容可以通过内存模型图的方式来帮助同学理解和学习。比如对象的继承和方法重写,对象的向上向下转型,内部类,静态变量和静态方法等内容。这部分也是较好的研究方向。
参考文献:
[1] 宋平,王振.提高Java语言教学效果的探索与实践[J].沈阳农业大学学报(社会科学版),2006,8(4):693-695.
[2] 张大鹏.内存模型在程序设计教学中的应用研究[J].福建电脑,2010,26(4):183.
[3] 曾蓉.C语言教学难点初探[J].中国职业技术教育,2003(10):59-61.
[4] 惠华先,张静.Java语言中对象内存分配过程的研究[J].电脑知识与技术,2011,7(8):1799-1801.
[5] 黑马程序员.Java基础案例教程[M].北京:人民邮电出版社,2017.
【通联编辑:闻翔军】