天天看點

java中值傳遞和引用傳遞的深入了解

1.先了解jvm的記憶體空間的配置設定:

java程式運作都需要開辟空間,java虛拟機運作時也要開辟空間的:

分為五片區域:寄存器、本地方法區、方法區、棧記憶體、堆記憶體

 棧記憶體:棧記憶體首先是一片記憶體區域,存儲的都是局部變量,凡是定義在方法中的都是局部變量(方法外的是全局變量),for循環内部定義的也是局部變量,是先加載函數才能進行局部變量的定義,是以方法先進棧,然後再定義變量,變量有自己的作用域,一旦離開作用域,變量就會被釋放。棧記憶體的更新速度很快,因為局部變量的生命周期都很短。

       堆記憶體:存儲的是數組和對象(其實數組就是對象),凡是new建立的都是在堆中,堆中存放的都是實體(對象),實體用于封裝資料,而且是封裝多個(實體的多個屬性),如果一個資料消失,這個實體也沒有消失,還可以用,是以堆是不會随時釋放的,但是棧不一樣,棧裡存放的都是單個變量,變量被釋放了,那就沒有了。堆裡的實體雖然不會被釋放,但是會被當成垃圾,Java有垃圾回收機制不定時的收取。

比如主函數裡的語句   int [] arr=new int [3];在記憶體中是怎麼被定義的:

      主函數先進棧,在棧中定義一個變量arr,接下來為arr指派,但是右邊不是一個具體值,是一個實體。實體建立在堆裡,在堆裡首先通過new關鍵字開辟一個空間,記憶體在存儲資料的時候都是通過位址來展現的,位址是一塊連續的二進制,然後給這個實體配置設定一個記憶體位址。數組都是有一個索引,數組這個實體在堆記憶體中産生之後每一個空間都會進行預設的初始化(這是堆記憶體的特點,未初始化的資料是不能用的,但在堆裡是可以用的,因為初始化過了,但是在棧裡沒有),不同的類型初始化的值不一樣。是以堆和棧裡就建立了變量和實體:

java中值傳遞和引用傳遞的深入了解

     那麼堆和棧是怎麼聯系起來的呢?

     我們剛剛說過給堆配置設定了一個位址,把堆的位址賦給arr,arr就通過位址指向了數組。是以arr想操縱數組時,就通過位址,而不是直接把實體都賦給它。這種我們不再叫他基本資料類型,而叫引用資料類型。稱為arr引用了堆記憶體當中的實體。(可以了解為c或c++的指針,Java成長自c++和c++很像,優化了c++)                                                                

java中值傳遞和引用傳遞的深入了解

              如果當int [] arr=null;

              arr不做任何指向,null的作用就是取消引用資料類型的指向。

              當一個實體,沒有引用資料類型指向的時候,它在堆記憶體中不會被釋放,而被當做一個垃圾,在不定時的時間内自動回收,因為Java有一個自動回收機制,(而c++沒有,需要程式員手動回收,如果不回收就越堆越多,直到撐滿記憶體溢出,是以Java在記憶體管理上優于c++)。自動回收機制(程式)自動監測堆裡是否有垃圾,如果有,就會自動的做垃圾回收的動作,但是什麼時候收不一定。

             是以堆與棧的差別很明顯:

            1.棧記憶體存儲的是局部變量而堆記憶體存儲的是實體;

            2.棧記憶體的更新速度要快于堆記憶體,因為局部變量的生命周期很短;

            3.棧記憶體存放的變量生命周期一旦結束就會被釋放,而堆記憶體存放的實體會被垃圾回收機制不定時的回收。

----------------------------------------------------------------------------------------------------------------------------------

一種是按值傳遞:值傳遞是指在調用函數時将實際參數複制一份傳遞到函數中,這樣在函數中如果對參數進行修改,将不會影響到實際參數。簡單來說就是直接複制了一份資料過去,因為是直接複制,是以這種方式在傳遞時如果資料量非常大的話,運作效率自然就變低了,是以java在傳遞資料量很小的資料是值傳遞,比如java中的各種基本類型:int,float,double,boolean等類型的,具體可以自己測試。

代碼:

java中值傳遞和引用傳遞的深入了解

結果:

java中值傳遞和引用傳遞的深入了解

      另外一種是按引用傳遞:引用傳遞其實就彌補了上面說的不足,如果每次傳參數的時候都複制一份的話,如果這個參數占用的記憶體空間太大的話,運作效率會很底下,是以引用傳遞就是直接把記憶體位址傳過去,也就是說引用傳遞時,操作的其實都是源資料,這樣的話修改有時候會沖突,記得用邏輯彌補下就好了,具體的資料類型就比較多了,比如Object,二維數組,List,Map等除了基本類型的參數都是引用傳遞。

代碼:

java中值傳遞和引用傳遞的深入了解

結果:

java中值傳遞和引用傳遞的深入了解

有些文章中寫的是java中所有的傳參方式都是按值傳遞,這也說得通,無非就是文字遊戲,因為無論是按值傳遞還是按引用傳遞都是把值傳遞過去了,是以就叫按值傳遞

彙總:(1)值傳遞之後,這兩個值是互不影響的,而引用傳遞則會互相影響的,因為傳遞前後都通過引用對象指向同一個位址;

參考的文章有:

https://blog.csdn.net/pt666/article/details/70876410

https://blog.csdn.net/morgerton/article/details/54908592