Java到底是按值传递还是按引用传递?

今天刷牛客网的题,其中一题是这样的

 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

     

posted @ 2018-06-04 21:02  shadowdoor  阅读(176)  评论(0编辑  收藏  举报