今天刷牛客网的题,其中一题是这样的
1 public class Test1 { 2 3 public static void main(String[] args) { 4 Test1 t1 = new Test1(); 5 t1.first(); 6 } 7 8 public void first(){ 9 int i = 5; 10 Value v = new Value(); 11 v.i = 25; 12 second(v, i); 13 System.out.println(v.i + " " + i); 14 } 15 16 public void second(Value v, int i){ 17 i = 0; 18 v.i = 20; 19 Value val = new Value(); 20 v = val; 21 System.out.println(v.i + " " + i); 22 } 23 } 24 25 class Value { 26 public int i = 15; 27 }
最终输出是:15 0 20
我以为的输出是:15 0 15
我的疑问在于第20行。
从上面引发了一个问题,Java到底是按值传递还是按引用传递?
以前,认为是值传递,是通过一个简单的swap例子
1 public static void main(String[] args) { 2 int a = 10; 3 int b = 20; 4 swap(a, b); 5 System.out.println("此时a为: " + a); 6 System.out.println("此时b为: " + b); 7 } 8 9 public static void swap(int x, int y){ 10 int temp = x; 11 x = y; 12 y = temp; 13 System.out.println("此时x为: " + x); 14 System.out.println("此时y为: " + y); 15 System.out.println(); 16 }
结果为:
此时x为: 20 此时y为: 10 此时a为: 10 此时b为: 20
如果是按引用传递,那么结果就不会这样。
可是,牛客网上的那道题又把我绕进去了。翻了翻该题的评论,大部分都说是值传递,但是仍然有人说提出引用传递的疑问。
不得已,翻书,Java核心技术卷1 第十版 page118~121
还有,搜索相关话题
结论:Java按值传递
总结:
方法得到的是所有参数值的一个拷贝,特别是,方法不能修改传递给它的任何参数变量的内容。
解释:
无论方法的形参中放的是基本类型参数,还是引用类型参数,方法得到的永远只是一个拷贝或者副本。
所以,上面的swap例子中,swap方法的形参 x、y 只是一个原始参数的副本,但是他们的值都是一样的。
此时,我在swap方法里改变了 x、y 的值,也只是改变了副本的值,对原始值没有任何影响。
而对于引用参数的传递,传递的仍然是引用参数的副本,只不过这个副本里放的是参数的地址,也就是说,他们此时指向了同一个地址。
如果此时副本改变了此地址中的值,那么相应的引用参数所存的值也会被改变。
可是,为什么牛客网试题,第20行执行后,v 已经指向了 val,而 val 中 i 的值为15,最终first方法中输出的却是20呢?
因为 -- 当第20行还未执行时,v.i = 20, 此时 i 的值变为20,first方法中的 v 和 second 中形参的 v 还是指向同一地址的,
但是第20行执行过后,second 中的 v 已经指向 了一个新的地址,也就是 val 指向的地址,
那么, 这时候 second 中的 v 已经和 first 中的 v 断掉了联系,两者已经属于你走东,我走西,各无瓜葛的状态
所以,在后面 second 中的 v 你怎么样变,都影响不了原本的引用参数。
小结这段话:作为引用参数副本,只要后期不重新指向一个新的地址,那么副本改变指向地址中的值,引用参数中的值也会被改变
相关链接:http://www.cnblogs.com/clara/archive/2011/09/17/2179493.html
相关阅读:Java核心技术 卷1 第十版 Page118~121