Thinker

  - long way to go...

  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  24 随笔 :: 0 文章 :: 143 评论 :: 0 Trackbacks
先给出两个例子引出今天所要讨论的问题:
 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。
呵呵,好好体会吧。
欢迎来信指正错误。

http://www.blogjava.net/qujinlong123/
posted on 2007-04-16 19:52 Long 阅读(8973) 评论(18)  编辑  收藏 所属分类: Java

评论

# re: Java 是值传递还是引用传递? 2007-04-16 19:59 刘甘泉
老问题了,T.I.J里面也有详细的解释  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-04-17 10:16 嘎嘎
java传的是对象引用的地址??  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-04-17 12:18 Long
@嘎嘎
对于对象来说,java 传的是对象的引用  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-04-17 13:18 ice4x
对于值类型来说,传递的就是值,对于对象,传递的就是对象的引用。  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-04-18 13:30 静儿
本来觉得是很简单的问题 。经阁下一讲解,发现自己原来真的有点概念不清。谢谢了!  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-05-17 23:37 Jerry Tao
简单的说,Java 只有值传递。  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-05-18 00:32 Long
@Jerry Tao
不错,Java是只有值传递,但是这个“值”是别有深意的,而且也经常会困扰初学者的。  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-05-26 00:21 天涯客
楼主的例子上当然还涉及到一个问题:因为String是Imutable的  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-05-26 00:22 天涯客
楼主的例子上当然还涉及到一个问题:因为String是Immutable的   回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-05-26 00:40 Long
@天涯客
至于Java对String对象本身的管理对传递参数来说是无关系的,无论String是不是Immutable,它都是一个对象,对象的传递方式都是一样的。  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2007-07-02 16:42 青松
java是值传递.

只不过对象的引用是和对象是遥控器与电视的关系.遥控器和电视都没有变.
变的只是节目  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2010-06-21 10:48 ne_akari
这帖子居然在搜索第一页,害人不浅啊。  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2010-06-21 10:55 ne_akari
这个例子根本没有任何说服力,可以看出,博主本身并没有理解这个问题。
第一个String没有改变值可以说明,在这个例子中是值传递。
而第二个Person属性的值的改变,是示例方法里使用的是引用的形式来改变属性的,与对象本身的调用是值传递或者引用传递没有任何关系。
人们总是很轻易地相信一个事实,总是很轻易地得到一个结论,而不去考虑更多。
什么是值传递,什么是引用传递,这个定义你搞清楚了吗?
好好思考下吧,或者好好GOOGLE下吧,难道引用地址就不可以再被复制一份吗?你没想到的,有可能正是答案的所在。  回复  更多评论
  

# re: Java 是值传递还是引用传递?[未登录] 2010-07-13 12:14 java
@ne_akari
乱七八糟的SB回复  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2011-02-10 17:39 tone
tempStr = 0xA242,
tmpValue1 = 0xA24B,
tmpValue2 = 0xA242

你写的是什么,tmpValue1 和 tmpValue2 传的不都是引用??
因为他们是tmp临时的对象 然后接收了引用了

但是又要记住你这不是new出来的,是常量池中的数据所以,改变不了

而且
值参数传递那么, 等号= 左边的变量肯定是开辟一个新的地址(物理内存),然后把等号右边的地址中的内容弄过来,弄过来的是内容!

而引用传递, 就是 等号= 左边的就是一个地址(类似指针),然后把等号右边的地址给弄过来

  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2011-02-10 17:44 tone
@tone
我QQ669112773 你来找我  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2011-02-10 18:31 tone
对象也是引用传递啊

和数组一样 数组名 传的是它的首地址 引用传递
而后面的 元素或者说属性 的传递 是值传递  回复  更多评论
  

# re: Java 是值传递还是引用传递? 2011-05-23 10:19
楼主本来就有理解错误,JAVA本来就是用值传递.第一个就是典型的值传递,值传递是开辟一个新内存把原变量来指向的值复制过来...回去看一下值传递和引用传递概念再发文章吧,不要在这里误导人  回复  更多评论
  


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


网站导航: