不明白怎么那么多人对JAVA中的参数传递有疑问,Think In Java中指出“JAVA中只有值传递”(见3rd Edition P78注释1)。我觉得记住这点挺重要的。 参数传递有“值传递”和“引用传递”之分,那么首先要弄清楚什么是“值传递”,什么是“引用传递”,其区分准则是什么?(参考http://hi.baidu.com/alljava/blog/item/6dddd4ca4f19be46f31fe765.html) 区分准则:形参和实参的关系。如果形参是实参的拷贝,则为值传递;否则,如果形参是实参的引用,则为引用传递。 显然,引用传递,改变形参的值将会影响实参;而值传递改变形参的值不会影响实参。 不能根据实参为引用就判定为引用传递,也就是要区分传递引用与引用传递。 引用传递是C++的特性(C#等其它后继语言可能也沿袭了),其典型例子如下:#include <iostream> using namespace std; //值传递 //形参是实参的拷贝 void swapByValueTranf(int a, int b){ cout<<"形参地址: a = "<<&a<<", b = "<<&b<<" | swapByValueTranf"<<endl; int t = a; a = b; b = t; } //引用传递 //形参是实参的引用 void swapByReferenceTranf(int &a, int &b){ cout<<"形参地址: a = "<<&a<<", b = "<<&b<<" | swapByReferenceTranf"<<endl; int t = a; a = b; b = t; } void swapWithNonSense(int* a, int* b){ cout<<"形参地址: a = "<<&a<<", b = "<<&b<<" | swapWithNonSense"<<endl; int* t = a; a = b; b = t; } void swapWithSense(int* a, int* b){ cout<<"形参地址: a = "<<&a<<", b = "<<&b<<" | swapWithSense"<<endl; int t = *a; *a = *b; *b = t; } int main(){ int a = 4, b = 5; cout<<"beforeSwap: a = "<<a<<", b = "<<b<<endl; cout<<"实参地址: a = "<<&a<<", b = "<<&b<<endl; swapByReferenceTranf(a,b);//此为引用传递 cout<<"afterSwap: a = "<<a<<", b = "<<b<<endl; cout<<"beforeSwap: a = "<<a<<", b = "<<b<<endl; cout<<"实参地址: a = "<<&a<<", b = "<<&b<<endl; swapByValueTranf(a, b);//此为值传递 cout<<"afterSwap: a = "<<a<<", b = "<<b<<endl; cout<<"beforeSwap: a = "<<a<<", b = "<<b<<endl; cout<<"实参的值: a = "<<&a<<", b = "<<&b<<endl; swapWithNonSense(&a, &b);//值传递?引用传递 cout<<"afterSwap: a = "<<a<<", b = "<<b<<endl; cout<<"beforeSwap: a = "<<a<<", b = "<<b<<endl; cout<<"实参的值: a = "<<&a<<", b = "<<&b<<endl; swapWithSense(&a, &b);//值传递?引用传递 cout<<"afterSwap: a = "<<a<<", b = "<<b<<endl; return 0; } 只有swapByReferenceTranf是引用传递,其余均为值传递。通过swapByReferenceTranf和swapWithSense都可以成功实现交换,但调用swapByReferenceTranf时形参和实参的地址是一致的,调用swapByValueTranf时是不一样;其余两个实参的值就是地址,改变形参的值不会影响实参,但可以通过形参的引用特性(地址)改变对应存储单元的值。 现在来讨论下JAVA中的参数传递。对于基本类型,值传递,没有任何异议。对于非基本类型,则传递的是对象的引用,但并不是引用传递,因为形参只是实参的拷贝,改变形参的值不会影响实参。在JAVA中,改变形参的值不会影响实参的值是很显然的。所以JAVA中只有值传递。 特别说明:改变形参的值不会影响实参的值,与通过引用改变对象的属性是不一样的。正如下列程序输出结果为:“bbbbaaaa”,而不是“aaaaaaaa”,更不是“bbbbbbbb”。通过改变形参s的值并不影响实参s的值,但可以通过形参sb修改其属性(引用特性)。public class Main {{ private static void change(String s, StringBuffer sb) { s = "aaaa"; sb.setLength(0); sb.append("aaaa"); } public static void main(String[] args) { String s = "bbbb"; StringBuffer sb = new StringBuffer("bbbb"); chang(s, sb); System.out.print(s+sb); } } 重要文献链接:http://www.javaworld.com/javaworld/javaqa/2000-05/03-qa-0526-pass.htmlhttp://zangweiren.javaeye.com/blog/214369 上面写到的区分准则是我自己的理解,才发现居然有这种资料(20080725): Core Java: The term call by value means that the method gets just the value that the caller provides. In contrast, call by reference means that the method gets the location of the variable that the caller provides. Thus, a method can modify the value stored in a variable that is passed by reference but not in one that is passed by value. The Java programming language always uses call by value. That means that the method gets a copy of all parameter values. The Java Programming Language: All parameters to methods are passed "by value." In other words, values of parameter variables in a method are copies of the values the invoker specified as arguments.You should note that when the parameter is an object reference, it is the object reference not the object itselfthat is passed "by value." The Java Tutorials: Primitive arguments, such as an int or a double, are passed into methods by value.Reference data type parameters, such as objects, are also passed into methods by value. 参考:http://www.javanb.com/j2se/1/7162.html http://www.51bc.org.cn/Java/f553f0cc45683838/http://hi.baidu.com/javaroom/blog/item/64c298d45cc35702a08bb7f1.htmlhttp://dev.21tx.com/2004/07/08/10855.htmlhttp://blog.csdn.net/zunshanke2004/archive/2006/08/29/1136443.aspx

评论