一個實例理解Java Reference

Java Reference即Java的引用機制。當用類創建一個對象時,類中的成員變量被分配內存空間,這些內存空間稱爲該對象的實體,而對象中存放着引用,以確保實體由該對象操作使用。

Java的所有對象都是引用,類似於C和C++中的指針。Java類的方法如果包含引用類型的參數,那麼當該方法被調用時,向該方法參數傳遞的是傳值變量的引用。不同於C和C++中的指針,Java對象在調用含參數方法時,向方法中的參數傳遞的都是指定的值得副本,而不是向參數傳值的變量本身。因此,在方法體重,如果參數的值被改變,不會影響向其傳值的變量的值。

來看一個具體的實例。

class ChangeStr {
   private String myStr;
   
   ChangeStr(String str) {
      myStr = str;
   }
   
   public void setMyStr(String newStr) {
      myStr = newStr;
   }

   public String toString() {
      return myStr;
   }
}

public class Test {
   public static void main(String[] args) {
      Test t = new Test();
      
      System.out.println("==== Test 1 ====");
      ChangeStr changeStr1 = new ChangeStr("Hello");
      System.out.println(changeStr1);
      t.change1(changeStr1);
      System.out.println(changeStr1);
      System.out.println();

      System.out.println("==== Test 2 ====");
      ChangeStr changeStr2 = new ChangeStr("Hello");
      System.out.println(changeStr2);
      t.change2(changeStr2);
      System.out.println(changeStr2);
      System.out.println();
   }
  
   // Method 1
   public void change1(ChangeStr cs) {
      cs.setMyStr("Hi");
      cs = new ChangeStr("HaHa");
   }

   // Method 2
   public void change2(ChangeStr cs) {
      cs = new ChangeStr("HaHa");
      cs.setMyStr("Hi");
   }
}

類Test有兩個含參方法change1()和change2(),這兩個方法的不同之處在於,方法體兩個語句的順序不同。

程序輸出如下:

==== Test 1 ====

Hello

Hi

 

==== Test 2 ====

Hello

Hello



從輸出結果可以看出,方法change1()改變了changeStr1的成員變量myStr的值,而change2()並沒有改變changeStr2的成員變量myStr的值。

針對test1,程序執行到第22行時,創建了一個ChangeStr實例changeStr1,並將其成員變量myStr賦值爲”Hello”,如圖所示。


當程序執行到第24行時,changeStr1的副本被傳遞給方法參數cs,這個副本的名字仍爲cs,這時cs與changeStr1指向同一個實體,見下圖:


在change1()方法體內,程序執行第38行時,cs調用方法setMyStr()改變了它所指向的實體的成員變量myStr的值,由於changeStr1與cs指向相同的實體,因此changteStr1的成員變量myStr的值便被更改爲”Hi”。


在change1()方法體內,程序執行第39行時,cs指向了一個新的實體,該實體的成員變量myStr的值爲”HaHa”,這對changeStr1無影響。


針對test2,程序執行到第29行時,與test1一樣,創建了一個ChangeStr實例changeStr2,並將其成員變量myStr賦值爲”Hello”,如圖所示。


同樣,當程序執行到第31行時,changeStr2的副本被傳遞給方法參數cs,這個副本的名字仍爲cs,這時cs與changeStr2指向同一個實體,見下圖:


在change2()方法體內,程序執行第44行時,與test1不同的是,這時cs指向了一個新的實體,該實體的成員變量myStr的值爲”HaHa”,而這對changeStr2無影響。


此後,當程序執行第45行時,cs調用方法setMyStr()改變了它所指向的實體的成員變量myStr的值,由於changeStr2與cs指向不同的實體,因此這對changteStr2仍然無影響。


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