Java方法參數是引用呼叫還是值調用
方法呼叫(call by) 是一個標準的電腦科學術語。方法呼叫根據參數傳遞的情況又分為值呼叫( call by reference ) 和參考呼叫( call by value ) 。江湖上有很多關於這兩種調用的定義 ,最通常的說法是傳遞值的是值調用,傳遞地址的是引用調用。這其實很不恰當,這種說法很容易讓我們聯想到Java的物件參數傳遞是引用調用,實際上,Java的物件參數傳遞仍然是值調用 。
我們先用一段程式碼來證實為什麼Java的物件參數傳遞是值呼叫。
public class Employee { public String name=null; public Employee(String n){ this.name=n; } //将两个Employee对象交换 public static void swap(Employee e1,Employee e2){ Employee temp=e1; e1=e2; e2=temp; System.out.println(e1.name+" "+e2.name); //打印结果:李四 张三 } //主函数 public static void main(String[] args) { Employee worker=new Employee("张三"); Employee manager=new Employee("李四"); swap(worker,manager); System.out.println(worker.name+" "+manager.name); //打印结果仍然是: 张三 李四 } }
上面的結果讓人很失望,雖然形參物件e1,e2的內容交換了,但實參物件worker,manager並沒有互換內容。這裡面最重要的原因就在於形參e1,e2是實參worker,manager的位址拷貝。
大家都知道,在Java中物件變數名稱實際上代表的是物件在堆中的位址(專業術語叫做物件參考 )。在Java方法呼叫的時候,參數傳遞的是物件的參考。重要的是,形參和實參所佔的記憶體位址並不一樣,形參中的內容只是實參中儲存的物件所引用的一份拷貝。
如果大家對JVM記憶體管理中Java棧 的局部變數區 有所了解的話(可以參見《 Java 虛擬機體系結構 》),就很好理解上面這句話。在JVM執行上面的程式時,執行main方法和swap方法,會在Java堆疊中先後push兩個叫做堆疊幀 的記憶體空間。 main堆疊幀中有一塊叫局部變數區的記憶體用來儲存實參物件worker和manager的參考。而swap堆疊訊框中的局部變數區則儲存了形參物件e1和e2的參考。雖然e1和e2的引用值分別與worker和manager相同,但它們佔用了不同的記憶體空間。當e1和e2的引用發生交換時,下面的圖很清楚的看出完全不會影響worker和manager的引用值。
Java物件參數傳遞雖然傳遞的是位址(引用),但仍是值呼叫。是時候需要給引用呼叫和值呼叫一個準確的定義了。
值呼叫(call by value): 在參數傳遞過程中,形參和實參佔用了兩個完全不同的記憶體空間。形參所儲存的內容是實參儲存內容的一份拷貝。事實上,Java物件的傳遞就符合這個定義,只不過形參和實參所儲存的內容並不是常規意義上的變數值,而是變數的位址。咳,回過頭想想:變數的位址不也是一種值嗎!
引用呼叫(call by reference) : 在參數傳遞的過程中,形參和實參完全是同一塊記憶體空間,兩者不分彼此。 實際上,形參名和實參名只是程式設計中的不同符號,在程式運作過程中,記憶體中儲存的空間才是最重要的。不同的變數名並不能說明佔用的記憶體儲存空間不同。
大體上說,兩種呼叫的根本並不在於傳遞的是值還是位址(畢竟位址也是一個值),而是在於形參和實參是否佔用同一塊記憶體空間。事實上,C/C++的指針參數傳遞也是值調用,不信試試下面的C程式碼吧!
#include<stdio.h> void swap(int *a1,int *b1){ int *t=a1; a1=b1; b1=t; } int main(){ int x1=100; int x2=200; int *a=&x1; int *b=&x2; printf("%d %d\n",*a,*b); swap(a,b); printf("%d %d\n",*a,*b); return 0; }
但C/C++是有引用調用的,這就是C/C++一種叫做引用的變數宣告方法: int a; int &ra=a; 其中ra是a的別名,兩者在記憶體中沒有區別,佔用了同一個記憶體空間。而透過引用(別名)的參數傳遞就符合引用呼叫的特點了。大家可以去試試void swap(int &a1,int &b1);的運行結果。
透過本文大家應該知道Java方法參數是引用呼叫還是值呼叫了吧。
更多Java方法參數是引用呼叫還是值呼叫相關文章請注意PHP中文網!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

公司安全軟件導致部分應用無法正常運行的排查與解決方法許多公司為了保障內部網絡安全,會部署安全軟件。 ...

將姓名轉換為數字以實現排序的解決方案在許多應用場景中,用戶可能需要在群組中進行排序,尤其是在一個用...

系統對接中的字段映射處理在進行系統對接時,常常會遇到一個棘手的問題:如何將A系統的接口字段有效地映�...

在使用IntelliJIDEAUltimate版本啟動Spring...

在使用MyBatis-Plus或其他ORM框架進行數據庫操作時,經常需要根據實體類的屬性名構造查詢條件。如果每次都手動...

Java對象與數組的轉換:深入探討強制類型轉換的風險與正確方法很多Java初學者會遇到將一個對象轉換成數組的�...

Redis緩存方案如何實現產品排行榜列表的需求?在開發過程中,我們常常需要處理排行榜的需求,例如展示一個�...

電商平台SKU和SPU表設計詳解本文將探討電商平台中SKU和SPU的數據庫設計問題,特別是如何處理用戶自定義銷售屬...
