java到底是传值还是传引用

关键字:   java value reference 值 引用    


这个很基础很基础的问题今天才搞明白。

今天和同学讨论C++的一个函数的参数是指针的时候我无意说了一句,要是java的话就不用这么复杂了,一律传引用,于是就引起了java到底是传值还是传引用的讨论。

我之前的认识是这样的:在处理简单数据类型的时候毫无疑问是传值的,而当对象作为函数的参数的时候则是传的是引用。

但是事实证明我的认识还是错的,现在我当然明白了java的传参究竟是传什么,下面简单说一下:

可以说java不存在传递引用的情况,java只有一种传递方法就是传值,但是这个传值还是有一点小小的不同,例如在函数

java 代码



1. public void
2. //stub
3. sc.someMethod();   
4. // sc = new SomeClass();
5.    
6. }



中,其中当调用此函数

java 代码




 


1. SomeClass someClass = new
2. testRef(someClass);


作为形参的sc会生成实参someClass的一个拷贝,但是这个拷贝是someClass在栈空间指向堆空间的地址的拷贝,我们知道,当使用诸如A a = new A();的时候,实际上A a是在栈空间中获得了一个A对象的“引用”,当使用new A();初始化这个对象是,则是在堆空间中申请了空间同时将a指向堆空间中的地址。有了这些知识就不难理解,在方法testRef中通过.操作其实就是对传进来的实参someClass进行操作,因为此时sc是someClass地址,而若执行了sc = new SomeClass();sc的.操作变不会再对someClass产生影响,究其原因,是因为此时sc已经指向了堆空间中另一块SomeClass类大小的地址。

简单一点就是说,java在传递参数过程中若参数是对象传递的是对象地址的拷贝,也就是说传递的是地址的值。

这个故事告诉我:凡事不可想当然



补充,今天看sun出的SCJP指南,上面的解释比较科学


        可能会问你是否理解传递值到方法中时会发生什么结果。如果方法中的代码改变了变量,对外部的方法是否可见?直接引用 Peter van der Lindens 的 Java 程序员解答的一段话(在 http://www.afu.com)

//引用

所有的变量(基本类型值和对象的引用值)都是值传递。但是这不是全部情况,对象是经常通过 Java 的引用变量来操作的。所以也可以说对象是通过引用传递的(引用变量通过值传递) 。这是变量不使用对象的值而是像前一个问题那样描述的使用对象引用的值的结果。最后一行:调用者对基本类型参数(int,char 等)的拷贝在相应参数变化时不会改变。但是,在被调用方法改变相应作为参数传递的对象(引用)字段时,调用者的对象也改变其字段。//引用结束

   如果你来自 C++背景,你可能对值传递参数和用&符号传递引用参数熟悉。在 Java 中没有这样的选择,所有的都是值传递。但是看起来并不总是这样。如果你传递的对象是对象的引用,你不能直接对对象的引用进行操作。 所以如果你操作一个传递到方法的对象的字段, 结果就好像你按引用传递(任何改变结果都会返回到调用函数) 将对象引用作为方法变量

请看下面的例子

java 代码




 



1. class
2. public int i = 10;   
3. }   
4. public class
5. public static void
6. new
7.           o.amethod();   
8.            }   
9. public void
10. new
11. 10;   
12. "Before another = "+ v.i);   
13.                      another(v);   
14. "After another = "+ v.i);   
15. //End of amethod
16. public void
17. 20;   
18. "In another = "+ v.i);   
19. //End of another
20. }



程序的输出结果是

Before another = 10
In another = 20
After another = 20

     看变量 i 是怎么被修改的。如果 Java 总是值传递(也就是对变量的拷贝)  ,它是怎么被修改的呢?过程是这样的方法收到了句柄的拷贝或者对象的引用, 但是这个引用的作用类似于指向真实的指针。对这个字段的改变会反映到它所指的值。这有些像是在 C/C++中指针的自动间接应用的的作用。