摘要:在職業(yè)教育的課堂上,Java語言的教學(xué)更多地偏向代碼的練習(xí),由于Java虛擬機(jī)的說明文檔晦澀難懂,不方便引入Java虛擬機(jī)相關(guān)內(nèi)容,不利于學(xué)生理解程序。文章提出通過內(nèi)存模型圖的方法幫助學(xué)生理解和學(xué)習(xí)Java語言,并以傳值和傳引用為例進(jìn)行了實(shí)證研究。
關(guān)鍵詞:職業(yè)院校課堂教學(xué);Java語言堂教學(xué);內(nèi)存模型圖應(yīng)用
中圖分類號:G424 文獻(xiàn)標(biāo)識碼:A
文章編號:1009-3044(2024)27-0152-03
0 引言
在高職院校軟件相關(guān)的課程體系中,語言的教學(xué)大多從Java語言開始,Java語言雖然只是一門語言,但其有嚴(yán)謹(jǐn)?shù)闹误w系,Java虛擬機(jī)。Java語言的學(xué)習(xí)從更多的是從使用角度切入學(xué)習(xí),如果不能理解Java虛擬機(jī),對學(xué)生的語言掌握程度會(huì)有部分影響。針對這個(gè)問題,宋平、王振建議學(xué)生反復(fù)揣摩、修改和嘗試[1]。職業(yè)院校的課程設(shè)計(jì)更多的是對接產(chǎn)業(yè)鏈和企業(yè)技能需求,并沒有完善的學(xué)科支撐體系。在沒有學(xué)過電路和計(jì)算機(jī)組成原理的學(xué)科體系相關(guān)的課程,學(xué)生在面臨理解Java語言,尤其是Java語言中的面向?qū)ο蟛糠?,理解較為困難。針對此問題張大鵬提出了將內(nèi)存模型引入課堂,文獻(xiàn)中得出的結(jié)論是:引入內(nèi)存模型進(jìn)入課堂教學(xué)可以使學(xué)生理解更加深刻,降低了程序的抽象程度[2]。本人在課堂實(shí)踐中發(fā)現(xiàn)即使將內(nèi)存模型融入課堂教學(xué),對學(xué)生來說讓人比較難以理解,通過結(jié)合程序畫內(nèi)存模型圖的方式可以比較有效地幫助學(xué)生理解Java語言。曾榮在C語言教學(xué)難點(diǎn)探索時(shí),將內(nèi)存單元畫出來,結(jié)合內(nèi)存單元圖來講解C 語言中的難點(diǎn)也是一種比較好的參考[3]。綜上所述畫好內(nèi)存模型圖有助于同學(xué)更好地理解和學(xué)習(xí)Java 語言。
1 Java 內(nèi)存模型概述
惠華先總結(jié)了Java虛擬機(jī)內(nèi)存區(qū)域相關(guān)的內(nèi)容。Java虛擬機(jī)的內(nèi)存區(qū)域主要包含:方法區(qū)、堆、Java棧、PC寄存器和本地方法棧等5個(gè)區(qū)域[4]。
方法區(qū)主要包含:類型信息、常量池、字段信息、方法信息、類變量、一個(gè)指向ClassLoader的引用、一個(gè)指向class 的引用、一個(gè)指向class 對象的引用、方法表;堆中主要存儲(chǔ)句柄池和對象池、每個(gè)包含一個(gè)指向特殊數(shù)據(jù)結(jié)構(gòu)的指針;Java棧中主要由3部分組成:局部變量表、操作數(shù)棧和幀數(shù)據(jù)區(qū);PC寄存器用于保存機(jī)器的運(yùn)行狀態(tài);本地方法棧是指Java虛擬機(jī)用到的與本地方法相關(guān)的數(shù)據(jù)區(qū)。
內(nèi)存模型主要基于現(xiàn)有的計(jì)算機(jī)內(nèi)存結(jié)構(gòu),現(xiàn)有的計(jì)算機(jī)內(nèi)存類似一個(gè)指定長度的數(shù)組,數(shù)組下標(biāo)類似一個(gè)內(nèi)存地址。傳值和傳引用案例研究時(shí),重點(diǎn)關(guān)注:程序調(diào)用棧中存儲(chǔ)的程序執(zhí)行到那一行;局部變量表中存儲(chǔ)的8種基本數(shù)據(jù)類型和引用數(shù)據(jù)類型;堆區(qū)中會(huì)使用連續(xù)的內(nèi)存空間,存儲(chǔ)創(chuàng)建出來的對象信息;方法區(qū)中存儲(chǔ)的方法表、方法的信息和字符串常量池。
程序調(diào)用棧的內(nèi)存模型圖畫法:程序調(diào)用棧是一個(gè)棧型的結(jié)構(gòu),主要存儲(chǔ)程序執(zhí)行到那一行,在執(zhí)行函數(shù)調(diào)用時(shí),程序調(diào)用棧會(huì)發(fā)生入棧操作,如圖1所示。
當(dāng)棧底上面一行存儲(chǔ)的行號所在的函數(shù)執(zhí)行結(jié)束后,會(huì)發(fā)生出棧操作。之后程序會(huì)執(zhí)行棧底所在函數(shù)行號的下一行,直到Main函數(shù)執(zhí)行結(jié)束,整個(gè)程序調(diào)用棧銷毀。
局部變量表的畫法:局部變量表中存儲(chǔ)的主要是8種基本數(shù)據(jù)類型和引用數(shù)據(jù)類型,可以使用連續(xù)的內(nèi)存空間來存儲(chǔ)具體的數(shù)據(jù)類型,如圖2所示。
堆區(qū)的畫法:堆區(qū)主要存儲(chǔ)的是對象的信息,對象主要包含成員變量,方法表的引用等信息,如圖3 所示。
方法區(qū)的畫法:方法區(qū)主要存儲(chǔ)的是方法表(某個(gè)對象的各個(gè)方法引用),方法的實(shí)現(xiàn),字符串常量池等信息,如圖4所示。
2 內(nèi)存模型在教學(xué)中的應(yīng)用
在方法調(diào)用中,參數(shù)可以通過值傳遞或引用傳遞來傳遞給方法。值傳遞是一種將參數(shù)的值復(fù)制到方法中的過程。這種傳遞方式適用于簡單數(shù)據(jù)類型,如整數(shù)、浮點(diǎn)數(shù)和布爾值等。常用的值傳遞對應(yīng)的數(shù)據(jù)類型在Java中指的是8種基本數(shù)據(jù)類型:byte、short、int、long、float、double、char、boolean。
Java傳值的過程中,將某個(gè)變量傳遞給函數(shù),此變量在函數(shù)的作用域中可能會(huì)發(fā)生各種變化。當(dāng)函數(shù)執(zhí)行結(jié)束之后,外部調(diào)用方再次使用傳入方的那個(gè)變量,此變量的值依舊是傳入函數(shù)之前的那個(gè)值。
Java中的引用數(shù)據(jù)類型:
類:class
接口:interface
數(shù)組:array
引用數(shù)據(jù)類型就是指內(nèi)存空間可以同時(shí)被多個(gè)棧內(nèi)存引用。接下來通過一個(gè)案例分析對象的引用傳遞。
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 對象并實(shí)例化
11 Student stu2 = null; //聲明stu2對象,初始值為null
12 stu2 = stu1; //將stu1的內(nèi)存地址賦值給stu2
13 stu1.name = "小明"; //為stu1對象的name 屬性賦值
14 stu1.age = 20; //為stu2對象的age屬性賦值
15 stu2.age = 50;
16 stu1.read(); //調(diào)用stu1的方法
17 stu2.read();
18 }
19 } 程序執(zhí)行結(jié)果如下:
大家好,我是小明,年齡50。
大家好,我是小明,年齡50。
4 傳引用案例的內(nèi)存模型圖分析
第10 行代碼Student stu1 = new Student ();聲明stu1對象并實(shí)例化,程序在執(zhí)行new關(guān)鍵字代碼之后,會(huì)在內(nèi)存中創(chuàng)建new關(guān)鍵字后對應(yīng)的對象。程序調(diào)用棧中存儲(chǔ)的是程序執(zhí)行到那一行,當(dāng)前是第10行。局部變量表中存儲(chǔ)當(dāng)前程序可以使用的對象的引用,是stu1。堆區(qū)中存儲(chǔ)的是當(dāng)前可以使用的對象的資源,包括成員變量name和age,初始值Kuf0RP7JuSCUgF3r1kaRgmeCmSFqloJHN7JJYmMWCUo=分別是null和0,還有一個(gè)指向方法表的引用。方法區(qū)中主要存儲(chǔ)的是方法表包含read方法和read方法的實(shí)現(xiàn)。通過內(nèi)存模型圖將第10行代碼執(zhí)行后的內(nèi)存狀態(tài)表現(xiàn)出來,如圖5所示。
第11行代碼Student stu2 = null; 聲明stu2對象,但不對其進(jìn)行實(shí)例化,沒有實(shí)例化的對象的默認(rèn)初始值為null。通過內(nèi)存模型圖將第11行代碼執(zhí)行后的內(nèi)存狀態(tài)表現(xiàn)出來,如圖6所示。
第12行代碼stu2 = stu1; 把stu1對象的引用賦值給stu2,此時(shí)stu1和stu2指向同一個(gè)的內(nèi)存地址。通過內(nèi)存模型圖將第12行代碼執(zhí)行后的內(nèi)存狀態(tài)表現(xiàn)出來,如圖7所示。
第13 行代碼stu1.name = "小明";為stu1 對象的name屬性賦值。“小明”是一個(gè)非new關(guān)鍵字創(chuàng)建出來的字符串,存儲(chǔ)在Java虛擬機(jī)的字符串常量池中。字符串常量池也是方法區(qū)的一部分。通過內(nèi)存模型圖將第13行代碼執(zhí)行后的內(nèi)存狀態(tài)表現(xiàn)出來,如圖8 所示。
第14行stu1.age = 20; 為stu1對象的age 屬性賦值,使age的值變?yōu)?0。通過內(nèi)存模型圖將第14行代碼執(zhí)行后的內(nèi)存狀態(tài)表現(xiàn)出來,如圖9所示。
第15行stu2.age = 50; 為stu2對象的age 屬性賦值。賦值之后age的值變?yōu)?0。通過內(nèi)存模型圖將第15行代碼執(zhí)行后的內(nèi)存狀態(tài)表現(xiàn)出來,如圖10所示。
分析:stu1和stu2指向的是同一內(nèi)存地址,所以修改堆區(qū)的數(shù)據(jù)stu1和stu2都可以訪問到,最終stu1和stu2的屬性值相同,程序輸出的結(jié)果也相同。
5 總結(jié)
內(nèi)存模型圖是一種幫助理解程序的好方法。同學(xué)們通過對內(nèi)存模型的分析,可以比較清楚分析面向?qū)ο蟪绦蛟趦?nèi)存中的變化狀態(tài),更加準(zhǔn)確地理解程序。但同時(shí)也會(huì)面臨如下問題:首先內(nèi)存模型圖有助于幫助同學(xué)理解程序,并不能完全準(zhǔn)確地模擬程序在內(nèi)存中的變化狀態(tài);其次本例中的在畫內(nèi)存模型圖時(shí),會(huì)使用局部變量表、程序調(diào)用棧、堆區(qū)、方法區(qū)和字符串常量池等概念,也會(huì)部分增加學(xué)生的理解難度。綜上所述在教學(xué)實(shí)踐中有利于同學(xué)理解Java中的傳值和傳引用,借助內(nèi)存模型圖來教學(xué)是一種比較好的教學(xué)方法。
本文重點(diǎn)是傳值和傳引用的研究案例,由于在Java語言教學(xué)中,有較多的學(xué)習(xí)內(nèi)容比較靠近Java虛擬機(jī),這部分內(nèi)容可以通過內(nèi)存模型圖的方式來幫助同學(xué)理解和學(xué)習(xí)。比如對象的繼承和方法重寫,對象的向上向下轉(zhuǎn)型,內(nèi)部類,靜態(tài)變量和靜態(tài)方法等內(nèi)容。這部分也是較好的研究方向。
參考文獻(xiàn):
[1] 宋平,王振.提高Java語言教學(xué)效果的探索與實(shí)踐[J].沈陽農(nóng)業(yè)大學(xué)學(xué)報(bào)(社會(huì)科學(xué)版),2006,8(4):693-695.
[2] 張大鵬.內(nèi)存模型在程序設(shè)計(jì)教學(xué)中的應(yīng)用研究[J].福建電腦,2010,26(4):183.
[3] 曾蓉.C語言教學(xué)難點(diǎn)初探[J].中國職業(yè)技術(shù)教育,2003(10):59-61.
[4] 惠華先,張靜.Java語言中對象內(nèi)存分配過程的研究[J].電腦知識與技術(shù),2011,7(8):1799-1801.
[5] 黑馬程序員.Java基礎(chǔ)案例教程[M].北京:人民郵電出版社,2017.
【通聯(lián)編輯:聞翔軍】