一个实例理解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仍然无影响。


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