天天看點

Java 基礎【04】數組記憶體配置設定

       可能Java 數組大家都很熟悉,最近我遇到了一個關于Java 數組記憶體配置設定的問題。

        突然發現許多書上“基本資料類型存儲在棧記憶體當中,對象則儲存在堆記憶體”這句話完全是錯誤的。下面是個簡單的例子代碼:

Java 基礎【04】數組記憶體配置設定
Java 基礎【04】數組記憶體配置設定

    “Java 數組大小是不能改變的”這可能大家都聽過,那上面這段代碼就有問題了。

    animal [] 長度為4,而names [] 數組的長度隻有3,但是經過一個指派語句,兩個數組的大小就都變為4了。

    這不是改變了數組的大小嗎?

    好吧,問問技術前輩吧,對數組的存儲方式有了全新的認識。

    下面是我的一點了解:(如果有錯誤的,剛好被大神你看到了,也請你能夠指出來。)

    上面的的 names 和 animal 不代表這個數組對象,僅僅是數組的變量而已,和C裡面的指針是一樣的,這樣的變量叫做引用變量。

    數組對象是儲存在堆記憶體當中,大小當然是不能改變的,但是數組變量卻能夠指向其他的數組對象,可以看看下面這個圖:

Java 基礎【04】數組記憶體配置設定

    藍虛線是指派語句 names = animal; 之前 names 和 animal 數組變量指向的堆記憶體當中數組對象;

    紅線是是指派語句 names = animal;之後 names 和 animal 數組變量都同時指向一個數組對象。當然這時候 Java 垃圾回收機制這時候就會發現那個沒人引用的數組對象然後把它帶走。

    從上面還可以看到,“Michael”,"Orson","Andrew" 這些都是基本的資料類型吧。但是他們卻存儲在堆記憶體當中。  

    實際上應該這樣說:局部變量放在棧記憶體當中,(像上面的 names[],animal[] 這種引用類型的變量,還有一些基本類型的變量),但應用變量所引用的對象是儲存是堆記憶體當中的。(包括數組還有一些我們平常寫的普通的類對象)

    Java在堆記憶體當中的對象通常是不允許直接通路的,但你可以想到直接通路的後果。為了通路堆記憶體當中的對象,這時候就需要引用變量這個中介。

    什麼時候Java存儲在棧記憶體中的變量是僅僅是引用變量? 什麼時候它又換了身份變為貨真價實的JAVA對象納?嗯,看看下面這個例子:

Java 基礎【04】數組記憶體配置設定
Java 基礎【04】數組記憶體配置設定

     隻有當棧記憶體中的引用變量調用了對象的方法或者是指向了對象的屬性的時候,它就從變量真正成了對象了。

   (比如上面例子中的 cat,dog 對象引用變量,animal[]數組變量)。 通過  

    animal[0] = dog;

    animal[1] = cat;

    使得兩個變量都指向了存儲在堆記憶體當中的對象,是以他們倆個列印出來的資訊是一模一樣的。

    上圖中藍線是指派語句:

    animal[0] = dog; animal[1] = cat;

    之前的變量指向的狀态,紅虛線是指派語句之後的狀态,animal[0]和dog ,animal[1] 和cat 所指向的都是相同的堆記憶體空間。