对于java中的值传递和引用传递一直颇受争论,《Core Java》的作者,以及JAVA的创造者James Gosling都认为当一个对象或引用类型变量被当作参数传递时,也是值传递,这个值就是对象的引用,因此JAVA中只有值传递,没有引用传递。还有一种说法是引用可以看作是对象的别名,当对象被当作参数传递给方法时,传递的是对象的引用,因此是引用传递。而《Thinking in Java》一书的作者Bruce Eckel则站在了中立的立场上。
大都数人其实都倾向于第一种说法,java中没有引用传递,本人也更倾向于第一种解释,下面讲讲个人的见解。
首先明白几个概念,什么是值传递,引用传递和指针传递?特别注意一下引用传递的概念,这个最早应该是出现在c++中,c中没有这个概念,c只有值传递和指针传递。
值传递:传递实参的一个复本给形参,在被调函数内对形参的修改不会影响到原来的实参
引用传递(c++中的定义):形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形参虽然也作为局部变量在栈中开辟了内存空间,但是这时存 放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的 任何操作都影响了主调函数中的实参变量。
指针传递:本质还值传递,把指针的值复制一份传递给形参,都指向实参指针指向的值,当对形参指向的内容操作时,就相当于对实参本身进行的操作。
其实引用传递和指针传递的实质是一样的,从汇编层面是无法区别两者的,引用是C++对指针的一种封装,方便使用,其实质和指针引用一样。纠正一下C++程序设计(谭浩强)中的一个问题,书上介绍引用的地方第198页说引用不是一个独立的变量,不单独占内存单元,这个说法不严谨,引用类型的参数也要占用内存空间的,保存的数据是一个地址。
再来看看Java中所谓的引用传递,其实和c++中的指针传递是一样的,指针传递的本质是值传递,所以可以说java中没有引用传递。
附一道面试题,来测试下对上面的理解,写出程序运行结果!
public class TestMain { /** * @author lcq * @date 2013-4-8 * @param args */ public static void main(String[] args) { String a = "a"; String b = "b"; operator(a, b); StringBuilder x = new StringBuilder("x"); StringBuilder y = new StringBuilder("y"); operator(x, y); System.out.println(a + "," + b); System.out.println(x + "," + y); } public static void operator(String a, String b) { a += b; b = a; } public static void operator(StringBuilder a, StringBuilder b) { a.append(b); b = a; } }
正确的答案是
a,b
xy,y
你,答对了嘛?