java到底是值傳遞還是引用傳遞

轉子guhanjie博客:http://guhanjie.iteye.com/blog/1683637

值傳遞例子

    ... ...  
    //定義了一個改變參數值的函數  
    public static void changeValue(int x) {  
    x = x *2;  
    }  
    ... ...  
    //調用該函數  
    int num = 5;  
    System.out.println(num);  
    changeValue(num);  
    System.out.println(num);  
    ... ...  

答案顯而易見,調用函數changeValue()前後num的值都沒有改變。

由此做一個引子,我用圖表描繪一個值傳遞的過程:

這裏寫圖片描述

num作爲參數傳遞給changeValue()方法時,是將內存空間中num所指向的那個存儲單元中存放的值,即”5”,傳送給了changeValue()方法中的x變量,而這個x變量也在內存空間中分配了一個存儲單元,這個時候,就把num的值5傳送給了這個存儲單元中。此後,在changeValue()方法中對x的一切操作都是針對x所指向的這個存儲單元,與num所指向的那個存儲單元沒有關係了!

自然,在函數調用之後,num所指向的存儲單元的值還是沒有發生變化,這就是所謂的“值傳遞”!值傳遞的精髓是:傳遞的是存儲單元中的內容,而非地址或者引用!

java中的對象參數是怎麼傳遞的:

    ... ...  
    class person {  
    public static String name = "Jack";  
    ... ...  
    }  
    ... ...  
    //定義一個改變對象屬性的方法  
    public static void changeName(Person p) {  
    p.name = "Rose";  
    }  
    ... ...  
    public static void main(String[] args) {  
    //定義一個Person對象,person是這個對象的引用  
    Person person = new Person();  
    //先顯示這個對象的name屬性  
    System.out.println(person.name);  
    //調用changeName(Person p)方法  
    changeName(person);  
    //再顯示這個對象的name屬性,看是否發生了變化  
    System.out.println(person.name);  
    }  

答案應該大家都心知肚明:

第一次顯示:“Jack”

第二次顯示:“Rose”

這裏寫圖片描述

主函數中new 了一個對象Person,實際分配了兩個對象:新創建的Person類的實體對象,和指向該對象的引用變量person。

【注意:在java中,新創建的實體對象在堆內存中開闢空間,而引用變量在棧內存中開闢空間】

正如如上圖所示,左側是堆空間,用來分配內存給新創建的實體對象,紅色框是新建的Person類的實體對象,000012是該實體對象的起始地址;而右側是棧空間,用來給引用變量和一些臨時變量分配內存,新實體對象的引用person就在其中,可以看到它的存儲單元的內容是000012,記錄的正是新建Person類實體對象的起始地址,也就是說它指向該實體對象。

這時候,好戲上臺了:

調用了changeName()方法,person作爲對象參數傳入該方法,但是大家特別注意,它傳入的是什麼!!!person引用變量將自己的存儲單元的內容傳給了changeName()方法的p變量!也就是將實體對象的地址傳給了p變量,從此,在changeName()方法中對p的一切操作都是針對p所指向的這個存儲單元,與person引用變量所指向的那個存儲單元再沒有關係了!

回顧一下上面的一個值傳遞的例子,值傳遞,就是將存儲單元中的內容傳給調用函數中的那個參數,這裏是不是異曲同工,是所謂“值傳遞”,而非“引用傳遞”!!!

那爲什麼對象內部能夠發生變化呢?

那是因爲:p所指向的那個存儲單元中的內容是實體對象的地址,使得p也指向了該實體對象,所以才能改變對象內部的屬性!

這也是我們大多數人會誤以爲是“引用傳遞”的終極原因!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章