方法呼叫(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中文網!

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

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

SublimeText3 Linux新版
SublimeText3 Linux最新版

Atom編輯器mac版下載
最受歡迎的的開源編輯器

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

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器