Java究竟是按值传递仍是按引用传递?

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

 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  20spa

 

我觉得的输出是:15  0  15code

个人疑问在于第20行。htm


 

从上面引起了一个问题,Java究竟是按值传递仍是按引用传递?blog

之前,认为是值传递,是经过一个简单的swap例子class

 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