關於Java對象做爲參數傳遞是傳值仍是傳引用的問題

前言

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

Object obj = new Object();

這句話的意思是:建立一個Object對象,再建立一個名爲obj的引用,讓這個引用指向這個對象,以下圖所示:函數

在有了上面的基礎以後,咱們便來看下面這組在網上很流行的例子:spa

 

基本數據類型做爲參數傳遞:

例1:.net

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)做爲參數傳遞時,傳遞的是實參值的副本,即傳的是值,不管在函數中怎麼操做這個副本,實參的值是不會被改變的。因此以上代碼執行的結果是: 
   3d

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

 

對象做爲參數傳遞:

  在下面的例2中,咱們把StringBuffer對象做爲參數傳遞到change函數。 
   
  例2:code

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中,當對象做爲參數傳遞時,傳遞的是該對象的引用呢?咱們再來看下面這個例子: blog

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」,以下圖所示: string

 

在例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

相關文章
相關標籤/搜索