請注意,java中沒有引用傳遞-----轉載

  1 說明:本文的適用對象爲java初學者、若是有讀者發現文章中有敘述不妥之處,請指正。
  2 
  3 今天在論壇上有人提了一個關於java中調用函數時有沒有引用傳遞的問題,可謂是吵的不可開交。有人說java只有值傳遞,也有人說java既有值傳遞也有引用傳遞,那麼java中到底有沒有引用傳遞呢,下面我來分析一下。
  4 
  5 1、首先來明確一下"值傳遞"和"引用傳遞的"區別
  6 
  7 值傳遞:是對所傳遞參數進行一次副本拷貝,對參數的修改只是對副本的修改,函數調用結束,副本丟棄,原來的變量不變(即實參不變)
  8 引用傳遞:參數被傳遞到函數時,不復制副本,而是直接將參數自身傳入到函數,函數內對參數的任何改變都將反映到原來的變量上。
  9 2、java中引用的含義
 10 
 11 C++和java中都有引用的概念,但在這兩種語言中卻有徹底不一樣的含義。C++中咱們能夠用形如"int &b=a」的形式來定義變量a的一個引用b,b只是a的一個別名,b和a在內存中佔同一個存儲單元,利用引用機制咱們能夠在調用函數時實現值的雙向傳遞——即引用傳遞,看下面代碼:
 12 
 13 示例一
 14 
 15 #include <iostream>
 16 
 17 using namespace std;
 18 
 19 int main()
 20 
 21 {
 22 
 23   void swap(int &,int &);
 24 
 25   int i=3,j=5;
 26 
 27   swap(i,j);
 28 
 29   cout<<"i="<<i<<"j="<<j<<endl;
 30 
 31   return 0;
 32 
 33 }
 34 
 35  
 36 
 37 void swap(int &a,int &b)
 38 
 39 {
 40 
 41   int temp;
 42 
 43   temp=a;
 44 
 45   a=b;
 46 
 47   b=temp;
 48 
 49 }
 50 
 51 執行上面的程序輸出的是i=5 j=3,a和b傳遞給swap()函數的時候,是傳遞的他們自己的地址,不是他們的拷貝,因此在函數中對他們的改變能夠直接影響到實參a和b,這就是引用傳遞。
 52 
 53 java中的引用更像C++中的指針,當咱們定義一個對象時(好比Person p=new Person()),定義的對象實例會放到java堆中,而變量p(即引用)會放到java棧中,p指向堆中的Person對象實例。
 54 
 55 3、對引用傳遞的認識誤區
 56 
 57 爲何有不少人認爲java有引用傳遞呢?一種狀況是有人認爲調用函數時其參數有多是引用(如上面的p),因此java有引用傳遞,這部分人對引用傳遞根本沒有正確的認識;而另外一種狀況看似有道理,可是仔細分析也是不正確的的,他們每每會用以下的代碼來證實他們的觀點:
 58 
 59 實例二:
 60 
 61 複製代碼
 62 class Demo{  
 63      int a;  
 64      public Demo(int a){  
 65          this.a=a;  
 66      }  
 67  }  
 68  public class TestQuote{  
 69      public static void main(String args[]){  
 70          Demo d1=new Demo(1);  
 71          Demo d2=new Demo(2);  
 72          System.out.println(d1.a);  
 73          System.out.println(d2.a);  
 74          function(d1,d2);  
 75          System.out.println(d1.a);  
 76          System.out.println(d2.a);  
 77      }  
 78      private static void function(Demo d1,Demo d2){  
 79          int a;  
 80          a=d1.a;  
 81          d1.a=d2.a;  
 82          d2.a=a;  
 83      }  
 84  }  
 85 複製代碼
 86 他們的觀點以下:執行上面的代碼,調用function()函數之前輸出的結果是一、2,調用function()函數以後輸出的結果會是二、1,可見在函數內對d1和d2的改變反映到了原來的變量上,要不是不會輸出二、1的。
 87 
 88 這種解釋是很迷惑人的,看上去好像很正確,下面的代碼會很好的反駁上面的觀點:
 89 
 90 示例三:
 91 
 92 複製代碼
 93 class Demo{  
 94      int a;  
 95      public Demo(int a){  
 96          this.a=a;  
 97      }  
 98  }  
 99  public class TestQuote{  
100      public static void main(String args[]){  
101          Demo d1=new Demo(1);  
102          Demo d2=new Demo(2);  
103          System.out.println(d1.a);  
104          System.out.println(d2.a);  
105          function(d1,d2);  
106          System.out.println(d1.a);  
107          System.out.println(d2.a);  
108      }  
109      private static void function(Demo d1,Demo d2){  
110          Demo temp;  
111          temp=d1;  
112          d1=d2;  
113          d2=temp;  
114      }  
115  } 
116 複製代碼
117 執行上面的代碼,調用function()先後程序輸出的都是一、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中只有值傳遞。
118 
119  
120 
121 可是網上有不少針對"java值傳遞和引用傳遞進行的區別"的文章,若是讀者看到的話必定要清楚,其中所說的引用傳遞是不正確的,他們所說的引用傳遞就是示例二中的那種狀況。不幸的是,網上有不少文章都把示例二中的那樣的傳遞看作引用傳遞,若是讀者看到知道是什麼意思就好了。
相關文章
相關標籤/搜索