Chan Chen Coding...

Java by value or by reference

Refer to: http://www.blogjava.net/qujinlong123/archive/2007/04/16/111060.html

先给出两个例子引出今天所要讨论的问题:

 1 
 2 public class Person
 3 {
 4   private String name = null;
 5   private int age = 0;
 6 
 7   public Person(String name, int age) {
 8     this.name = name;
 9     this.age = age;
10   }
11 
12   public void changeName(String newName) {
13     this.name = newName;
14   }
15 
16   public void changeAge(int newAge) {
17     this.age = newAge;
18   }
19 
20   public String toString() {
21     return "Person - Name: " + name + ", Age: " + age;
22   }
23 }
24 
25 public class PassByValue
26 {
27   public static void main(String[] args) {
28     // one example
29     String value1 = "value1: aaa";
30     String value2 = "value2: bbb";
31 
32     swapValue(value1, value2);
33 
34     System.out.println(value1);
35     System.out.println(value2);
36 
37     // another example
38     Person person = new Person("张三"20);
39 
40     System.out.println(person.toString());
41 
42     changePerson(person);
43 
44     System.out.println(person.toString());
45   }
46 
47   public static void swapValue(String tmpValue1, String tmpValue2) {
48     String tempStr = tmpValue1;
49     tmpValue1 = tmpValue2;
50     tmpValue2 = tempStr;
51   }
52 
53   public static void changePerson(Person tmpPerson) {
54     tmpPerson.changeName("李四");
55     tmpPerson.changeAge(30);
56   }
57 }
58 

考虑一下上面这段代码的输出结果是什么?
我相信绝大多数人都能快速的给出正确答案:
value1: aaa
value2: bbb
Person - Name: 张三, Age: 20
Person - Name: 李四, Age: 30
答案为什么是这样的呢?那么 Java 到底是按值传递还是按引用传递参数的呢?
例子1中的 swapValue() 方法不起作用,看起来是按值传递参数的,例子2中的 changeName() 和 changeAge() 方法起作用,从表面上看起来好像又是按引用传递参数的。呵呵,别急,先让我们来弄清楚一个重要的概念,就是 Java 操纵对象都是通过引用来实现的,所有的对象变量都是所指向的对象的引用,那也就是说所有对象变量的值并不是它所指向的对象本身,而是该对象的引用,这句话听起来可能有点让人犯晕,举个例子来说,String str = new String("aaa"); 这条语句的意思是 new 了一个值为 "aaa" 的字符串对象,然后用一个名字叫 str 的对象变量来指向它,保存它的引用,假设在内存中 new 出来的这个字符串对象的实际地址为 0xA242, 那么 str 的值实际上是 0xA242。
现在来看看例子1,假设 
String value1 = "value1: aaa" 的地址为 0xA242,
String value2 = "value2: bbb" 的地址为 0xA24B, 
然我们来看看 swapValue(value1, value2); 语句 Java 是怎么执行的。当程序执行到这句语句的时候,JVM 在栈中创建两个临时变量 tmpValue1,tmpValue2,用来接收传进来的 value1 和 value2 的值,而 value1 和 value2 的值分别为 0xA242 和 0xA24B,所以那两个临时变量 tmpValue1和tmpValue2 的值也被赋值为 0xA242 和 0xA24B,此时接下来的三条语句分别是 
tempStr = 0xA242, 
tmpValue1 = 0xA24B, 
tmpValue2 = 0xA242; 
此时 tmpValue1 的值是指向 "value2: bbb" 这个对象的,
   tmpValue2 的值是指向 "value1: aaa" 这个对象,你可以在 swapValue() 方法内部打印 tmpValue1 和 tmpValue2 的值验证一下。
不过这里的 tmpValue1和tmpValue2 是在栈中的临时变量,而并不是 main 方法中 value1和value2,main 方法中 value1和value2 的值并没有改变,那这里所谓的值传递是指什么呢?因为 value1 的值是 0xA242("value1: aaa" 这个对象的引用),而并不是 "value1: aaa" 这个对象,传递参数时传递的是 "value1: aaa" 这个对象的引用也就是 value1 的值,所以是值传递。
例子2也是一样的,假设
Person person = new Person("张三", 20) 的地址为 0xA242,
那么 person 的值是 0xA242, 那么通过调用 changePerson(person); 将 0xA242 传递给 tmpPerson, 也就是 tmpPerson 此时的值为 0xA242 也就是 new Person("张三", 20) 这个对象的引用,也就是说 tmpPerson 指向 new Person("张三", 20) 对象,对 tmpPerson 引用对象的修改实际上就是对 person 引用对象的修改,这看起来很想引用传递的概念,但实际上是值传递,为什么呢?因为在参数传递过程中传递的是 person 的值,也就是 0xA242。

-----------------------------------------------------
Silence, the way to avoid many problems;
Smile, the way to solve many problems;

posted on 2013-02-01 11:20 Chan Chen 阅读(195) 评论(0)  编辑  收藏 所属分类: Scala / Java


只有注册用户登录后才能发表评论。


网站导航: