請注意:java中沒有引用傳遞

來源:互聯網
上載者:User

說明:本文的適用對象為java初學者、如果有讀者發現文章中有敘述不妥之處,請指正。

今天在論壇上有人提了一個關於java中調用函數時有沒有引用傳遞的問題,可謂是吵的不可開交。有人說java只有值傳遞,也有人說java既有值傳遞也有引用傳遞,那麼java中到底有沒有引用傳遞呢,下面我來分析一下。

一、首先來明確一下"值傳遞"和"引用傳遞的"區別

值傳遞:是對所傳遞參數進行一次副本拷貝,對參數的修改只是對副本的修改,函數調用結束,副本丟棄,原來的變數不變(即實參不變)
引用傳遞:參數被傳遞到函數時,不複製副本,而是直接將參數自身傳入到函數,函數內對參數的任何改變都將反映到原來的變數上。
二、java中引用的含義

C++和java中都有引用的概念,但在這兩種語言中卻有完全不同的含義。C++中我們可以用形如"int &b=a”的形式來定義變數a的一個引用b,b只是a的一個別名,b和a在記憶體中占同一個儲存單元,利用引用機制我們可以在調用函數時實現值的雙向傳遞——即引用傳遞,看下面代碼:

樣本一

#include <iostream>

using namespace std;

int main()

{

  void swap(int &,int &);

  int i=3,j=5;

  swap(i,j);

  cout<<"i="<<i<<"j="<<j<<endl;

  return 0;

}

 

void swap(int &a,int &b)

{

  int temp;

  temp=a;

  a=b;

  b=temp;

}

執行上面的程式輸出的是i=5 j=3,a和b傳遞給swap()函數的時候,是傳遞的他們本身的地址,不是他們的拷貝,所以在函數中對他們的改變可以直接影響到實參a和b,這就是引用傳遞。

java中的引用更像C++中的指標,當我們定義一個對象時(比如Person p=new Person()),定義的對象執行個體會放到java堆中,而變數p(即引用)會放到java棧中,p指向堆中的Person對象執行個體。

三、對引用傳遞的認識誤區

為什麼有很多人認為java有引用傳遞呢?一種情況是有人認為調用函數時其參數有可能是引用(如上面的p),所以java有引用傳遞,這部分人對引用傳遞根本沒有正確的認識;而另一種情況看似有道理,但是仔細分析也是不正確的的,他們往往會用如下的代碼來證明他們的觀點:

樣本二:

 

view plaincopy to clipboardprint?
  1. class Demo{  
  2.      int a;  
  3.      public Demo(int a){  
  4.          this.a=a;  
  5.      }  
  6.  }  
  7.  public class TestQuote{  
  8.      public static void main(String args[]){  
  9.          Demo d1=new Demo(1);  
  10.          Demo d2=new Demo(2);  
  11.          System.out.println(d1.a);  
  12.          System.out.println(d2.a);  
  13.          function(d1,d2);  
  14.          System.out.println(d1.a);  
  15.          System.out.println(d2.a);  
  16.      }  
  17.      private static void function(Demo d1,Demo d2){  
  18.          int a;  
  19.          a=d1.a;  
  20.          d1.a=d2.a;  
  21.          d2.a=a;  
  22.      }  
  23.  }  

  

 

他們的觀點如下:執行上面的代碼,調用function()函數以前輸出的結果是1、2,調用function()函數之後輸出的結果會是2、1,可見在函數內對d1和d2的改變反映到了原來的變數上,要不是不會輸出2、1的。

這種解釋是很迷惑人的,看上去好像很正確,下面的代碼會很好的反駁上面的觀點:

樣本三:

 

view plaincopy to clipboardprint?
  1. class Demo{  
  2.      int a;  
  3.      public Demo(int a){  
  4.          this.a=a;  
  5.      }  
  6.  }  
  7.  public class TestQuote{  
  8.      public static void main(String args[]){  
  9.          Demo d1=new Demo(1);  
  10.          Demo d2=new Demo(2);  
  11.          System.out.println(d1.a);  
  12.          System.out.println(d2.a);  
  13.          function(d1,d2);  
  14.          System.out.println(d1.a);  
  15.          System.out.println(d2.a);  
  16.      }  
  17.      private static void function(Demo d1,Demo d2){  
  18.          Demo temp;  
  19.          temp=d1;  
  20.          d1=d2;  
  21.          d2=temp;  
  22.      }  
  23.  }   

 

執行上面的代碼,調用function()前後程式輸出的都是1、2,此程式試圖通過調用function()交換d1和d2,但是沒有成功,為什麼呢?因為d1和d2是值傳遞,function()中的d1和d2是main()函數中d1和d2的副本,調用完function()不會對main()中的變數產生影響。再看樣本二中,function()函數內改變的並不是d1和d2本身的值,而是d1和d2指向的對象的值,調用完function()後d1和d2仍然指向函數調用前的堆地址,即函數參數是棧中的d1和d2,而不是堆中d1和d2指向的對象,即使你在函數中改變了堆中的對象,但沒有改變函數參數的值。所以樣本二並不是什麼引用傳遞;可見java中只有值傳遞。

 

但是網上有很多針對"java值傳遞和引用傳遞進行的區別"的文章,如果讀者看到的話一定要清楚,其中所說的引用傳遞是不正確的,他們所說的引用傳遞就是樣本二中的那種情況。不幸的是,網上有很多文章都把樣本二中的那樣的傳遞看做引用傳遞,如果讀者看到知道是什麼意思就行了。

 

轉自 http://blog.csdn.net/lubiaopan/archive/2009/11/19/4837878.aspx

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.