本文漏的圖片已經補上,請放心閱讀。
前面的文章有時候會留一些思考題,主要是想讓大家多想想文章的內容,所以沒留答案,評論區回覆也是五花八門。寫這篇文章是想再幫大家鞏固一下之前的內容,子曾經說過:“溫故而知新,可以上王者”。Java中一共有四類八種基本資料型別,看下錶:
除掉這四類八種基本型別,其它的都是物件,也就是引用型別,包括陣列。
來看一段示例程式碼:
一個Person類,提供了一個構造方法,一些get/set方法:
下面是測試的main方法:
先看第一句程式碼:
方法體裡宣告的基本資料型別在棧記憶體裡,我們畫一下
繼續執行以下程式碼
對於基本資料型別來說,賦值(=號)就相當於拷貝了一份值,把int1的值100,拷貝給int2,繼續畫圖
int1=500,直接修改int1的值為500,表現如下圖
分別列印int1,int2的值,相信沒有人會答錯,分別是500,100。
再來看陣列的初始化
先初始化arr1,當執行到new這個關鍵字,會在堆記憶體分配記憶體空間,並把該記憶體空間的地址賦值給arr1。
繼續執行以下程式碼
這兒arr2初始化時並沒有new關鍵字,並不會在堆記憶體裡新開闢一塊空間,而是把arr1裡存的堆記憶體地址直接賦值給了arr2,對於引用型別來說,賦值(=號)就相當於拷貝了一份記憶體地址,也就是說arr1,arr2現在指向了同一塊堆記憶體,表現形勢如下圖
這時候執行如下程式碼
雖然只是修改arr1陣列下標位置為3的值
但由於陣列arr1和陣列arr2指向同一塊堆記憶體,列印arr1[3]和arr2[3]的值,都是8。你答對了嗎?
再來看物件的初始化
當看到這個new,這貨肯定在堆記憶體裡開闢了一塊記憶體空間,Person裡有一個叫name的String物件,String這個物件有點特殊,雖然沒有new這個關鍵字,但還是在堆記憶體中開闢了一塊空間,在String是一個很普通的類一文中已經講解過了,這裡就不再細講了,String底層是陣列實現的,陣列也是引用型別,age為基本資料型別,表現如下圖
上圖中大框裡的內容就是整個Person物件在堆記憶體中的體現,繼續執行以下程式碼
沒有new關鍵字,per2不會在堆記憶體中新開闢空間,和陣列一樣,也是把per1的記憶體地址直接賦值給了per2
當我們修改per1的屬性的時候
如下圖兩個紅框裡的內容,給物件(陣列也是物件)賦值其實就是相當於引用重新指向一塊堆記憶體,基本資料型別是直接修改值,表現如下圖
所以,不管列印per1還是per2的name、age,列印出來的結果都是“李四”、35,這個你也答對了嗎?最後,我們來驗證一下,結果是不是和文中說的一致。
結果完全一致,回過頭來看看Java裡的“==”比較符,結果就不難理解了,程式碼如下
結果分別是false,true,true,當==兩邊是基本資料型別時,==於比較的是兩邊的兩個值是否相等,當==兩邊是引用型別時比較的是兩個記憶體地址,也可以看成是看這兩個引用是否指向堆記憶體裡的同一塊地址,如下圖
新手在學習Java時,在引用型別上可能經常容易犯錯誤,如本文中所講的arr1,arr2,很多人在寫程式碼的時候是想拷貝一份值來用,卻不知道在修改arr1的時候,arr2的值也變了。
本篇內容就講解到這兒,畫圖不易,希望大家以後多想想變數在記憶體中的樣子,學習起來可以事半功倍。四類八種基本資料型別,本文只列舉了int型別,其它的7中基本型別和int的表現形式一致,這裡就不一一舉例了。
最後,說一下前面的文章留的文末思考,首先是讓人疑惑的Java程式碼一文中的文末思考
很簡單是false
兩個物件都是新new出來的,開闢了兩塊記憶體空間,i7和i8的引用不是指向堆記憶體裡的同一塊地址,因此列印出來是false。
至於Java中的陣列一文中的文末思考
相信認真看過本文的朋友都知道列印出來是多少了,還不清楚的,建議重新閱讀本文,直到弄明白為止。
注:char陣列的列印有點特殊,int陣列列印是列印出來一個地址,而char陣列是列印陣列裡的內容。本文中所有程式碼已經上傳至公眾號:saysayJava,需要請自行關注下載。
如果喜歡本系列文章,請為我點贊或順手分享,您的支援是我繼續下去的動力,您也可以在評論區留言想了解的內容,有機會本專欄會做講解,最後別忘了關注一下我。
轉載無限歡迎,但請註明「作者」和「原文地址」。轉載請在文中保留此段,感謝您對作者版權的尊重。如需商業轉載或刊登,請聯絡作者獲得授權