關於Java對象作為參數傳遞是傳值還是傳引用的問題


前言

  在Java中,當對象作為參數傳遞時,究竟傳遞的是對象的值,還是對象的引用,這是一個飽受爭議的話題。若傳的是值,那么函數接收的只是實參的一個副本,函數對形參的操作並不會對實參產生影響;若傳的是引用,那么此時對形參的操作則會影響到實參。 
  首先我們來看一句代碼:

Object obj = new Object();

這句話的意思是:創建一個Object對象,再創建一個名為obj的引用,讓這個引用指向這個對象,如下圖所示:

在有了上面的基礎之后,我們便來看下面這組在網上很流行的例子:

 

基本數據類型作為參數傳遞:

例1:

public class test {
    public static void main(String[] args) {
        int i = 1;
        System.out.println("before change, i = "+i);
        change(i);
        System.out.println("after change, i = "+i);
    }
    public static void change(int i){
        i = 5;
    }
}

 

 這個例子不難理解,當基本數據類型(Boolean,byte,char,String,int,Long,float,double)作為參數傳遞時,傳遞的是實參值的副本,即傳的是值,無論在函數中怎么操作這個副本,實參的值是不會被改變的。所以以上代碼執行的結果是: 
   

 before change, i = 1 
 after change, i = 1 

 

對象作為參數傳遞:

  在下面的例2中,我們把StringBuffer對象作為參數傳遞到change函數。 
   
  例2:

public class test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello ");
        System.out.println("before change, sb is "+sb.toString());
        change(sb);
        System.out.println("after change, sb is "+sb.toString());
    }
    public static void change(StringBuffer stringBuffer){
        stringBuffer.append("world !");
    }
}

為了方便推理出結論,我們先直接看程序的運行結果: 
   

  before change, sb is Hello 
  after change, sb is Hello world ! 

   
  從輸出結果中我們可以發現,sb所指向的對象的值被改變了,那么是否我們可以推論出,在Java中,當對象作為參數傳遞時,傳遞的是該對象的引用呢?我們再來看下面這個例子: 

public class test {
    public static void main(String[] args) {
        StringBuffer sb = new StringBuffer("Hello ");
        System.out.println("before change, sb is "+sb.toString());
        change(sb);
        System.out.println("after change, sb is "+sb.toString());
    }
    public static void change(StringBuffer stringBuffer){
        stringBuffer = new StringBuffer("Hi ");
        stringBuffer.append("world !");
    }
}

如果上面的推論是正確的,即Java中對象作為參數傳遞,實際傳遞的是該對象的引用,那么在調用change函數之后,原對象的值應該是會改變的,變為“Hi world !”,但是,當我們運行程序后,結果卻是如下所示: 
   

  before change, sb is Hello 
  after change, sb is Hello 

   
  原對象的值並沒有被改變,這與上面的推論相矛盾!為什么在Java中,當對象作為參數傳遞時,有的時候實參被改變了,而有的時候實參並未被改變呢?下面讓我們來分析一下其中的原因: 
  從文章的開頭我們知道,當執行StringBuffer sb = new StringBuffer(“Hello “)時,我們創建了一個指向新建對象“new StringBuffer(“Hello “)”的引用“sb”,如下圖所示: 

 

在例2中,當我們調用change函數后,實際上,形參stringBuffer也指向了實參sb所指向的對象,即: 

 

那么當我們執行stringBuffer.append(“world !”)后,便通過對象的引用“stringBuffer”修改了對象的值,使之變成了“Hello world !”,即: 

 

但是,在例3中的change函數中,我們又新建了一個對象“new StringBuffer(“Hi “)”(這實際上在內存中開辟了一塊在原對象地址之外的新區域),這讓形參stringBuffer實際指向了這個新建的對象,並將新對象的值設置為“Hi world !”,例三中stringBuffer的值已經被改變為了Hi world,但是因為值沒有被return返回賦值給sb對象,所以sb對象並沒有被改變,所以輸出的任然是hello,即:

 

那么我們就不難理解,為何在執行完change函數之后,實參的值仍為“Hello”了。 
  

結論

  綜上所述,我們可以得出結論:在Java中,當對象作為參數傳遞時,實際上傳遞的是一份“引用的拷貝”。 (實際傳遞的是對象的引用)

 

轉載自:https://blog.csdn.net/xiangwanpeng/article/details/52454479

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM