? ? ?
方法調用(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);的運行結果。
?
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
