一分钟理解Java包装类型
轉(zhuǎn)載自??一分鐘理解Java包裝類型
Java 一直標(biāo)榜自己是一個(gè)純粹的面向?qū)ο笳Z言,自作聰明的為所有的值類型都提供相應(yīng)的引用類型(不明白這兩個(gè)概念,看之前的《一分鐘理解傳值和傳引用》)比如:int 類型對(duì)應(yīng)的有 Integer,前者是一個(gè)值,后者是一個(gè)引用。為了方便二者的轉(zhuǎn)換又一個(gè)叫“自動(dòng)拆裝箱”的特性,把本來清晰的概念搞的亂七八糟。
一個(gè)優(yōu)秀的語言應(yīng)該語法簡單,語義單一、清晰。
本文討論它這些烏七八糟的概念(我也搞不懂),直接進(jìn)入正題——通過閱讀 JVM code 判斷究竟發(fā)生了什么。
解讀 class 文件
JVM 是一個(gè)棧式虛擬機(jī),它提供的指令都是圍繞著棧進(jìn)行的。通過javap -c <className>查看一個(gè) class 文件中的 JVM 指令。如下代碼,左邊是 Java 代碼右邊是它的 JVM code。
看一下每條指令執(zhí)行完后棧的變化:bipush 把數(shù)字 20 直接 push 到棧
invokestatic 調(diào)用一個(gè)靜態(tài)方法在堆中構(gòu)造一個(gè)對(duì)象,然后把對(duì)象的地址壓入到棧
astore_1 把 Integer 對(duì)象的內(nèi)存地址記錄到一個(gè)內(nèi)部變量中(JVM 在堆中維護(hù)了一張大的變量表,代表變量名和變量值的關(guān)系,可以想象成 HashMap。)
至此,Integer = 20 這句代碼執(zhí)行完畢。緊接著看,bipush 把 10 壓入棧
asotre2 把變量 b 和棧中的 10 做關(guān)聯(lián)(放到變量表中)
總結(jié):
-
值變量所指向的內(nèi)容(值)是放在棧中的,訪問時(shí)直接操作棧
-
引用變量所指向的內(nèi)容(對(duì)象)是放在堆中的,訪問時(shí)先把變量載入到棧(通過aload_1 指令,例子中沒有出現(xiàn)),再操作。
訪問包裝對(duì)象時(shí)發(fā)生了什么
Integer c = null; Integer d = 10; int e = c + d;JVM code 為
-
包裝對(duì)象的空指針問題
aconst_null 把一個(gè)空指針壓入棧,astore_1 把棧頂?shù)淖兞糠湃氲阶兞勘碇?#xff0c;所以此時(shí) a 是 null,所以會(huì)出現(xiàn)空指針錯(cuò)誤。
-
包裝對(duì)象的計(jì)算方法
8-16 是計(jì)算兩數(shù)相加,aload_1 把變量表中的變量壓入棧,invokervirtual 指令把對(duì)象轉(zhuǎn)換成 int 重新入棧;12、13 行的邏輯也是如此。 16 行執(zhí)行整數(shù)相加。因?yàn)橛?jì)算結(jié)果是 int 類型,所以最后通過 isotre_3 放到變量表。
自己分析
如果代碼的最后一行寫作Integer e = c + d;,JVM code 會(huì)變成
?
自己動(dòng)手分析一下看看吧。
總結(jié)
Java 的包裝數(shù)據(jù)類型非常蹩腳,這是它為了追求“表面的面向?qū)ο蟆倍冻龅拇鷥r(jià)。裝逼之勢(shì)如雷霆萬鈞,可怕。
總結(jié)
以上是生活随笔為你收集整理的一分钟理解Java包装类型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 打印机墨盒上机不认故障解决打印机显示墨盒
- 下一篇: IE浏览器在电脑哪里电脑如何找到浏览器