一道简单的笔试题,可是我有点想不通

2015-07-13 12:05:18 +08:00
 sophie2805
class Value{
public int i=15;
}
public class Test{
public static void main(String argv[]){
Test t=new Test( );
t.first( );
}

public void first( ){
int i=5;
Value v=new Value( );
v.i=25;
second(v,i);
System.out.println(v.i);
}

public void second(Value v,int i){
i = 0;
v.i = 20;
Value val = new Value( );
v = val;
System.out.println(v.i+" "+i);
}
}
4186 次点击
所在节点    Java
21 条回复
sophie2805
2015-07-13 12:07:00 +08:00
答案是
15 0
20


为啥不是
15 0
15

second方法调用结束的时候,v此时其实是指向val的对吗?那v.i不就是15吗
sophie2805
2015-07-13 12:09:06 +08:00
自己也在IDEA里面运行了,单步了,确实是
15 0
20

为啥~~从second结束,回到first方法里面,v.i就变成20了。。。苍天呐,为啥啊
sampeng
2015-07-13 12:26:31 +08:00
你需要了解函数的参数传值以及对象在内存里面真实结构的相关知识
传值引用、传址引用
kalintw
2015-07-13 12:31:01 +08:00
@sophie2805

原因是second中这行代码:
v.i = 20;

java的对象做形式参数,是按对象指针传值的。
second传参传进来的v是first中v的“值”拷贝。也就是说,这两个v变量本身在内存中是两块地方,是两个对象指针变量。 但是它们指向的地址(也就是对象内容的内存结构)是一样的。就好比你大名如花,小名阿花,指向的都是你。

second传参传进来的v, 和first中v,指向的都是first中new出来的那个Value对象,同一块内存内容。你在second中通过拷贝v修改了该对象的i为20。然后在first中再通过原来的v访问,当然也是20。
BuilderQiu
2015-07-13 12:32:45 +08:00
他从来没变过,一直都是20.

主要搞清这一步:
Value val = new Value( );
v = val;

这个对原来的v没有什么卵用,只是将v指向val的地址了,后续操作v都是操作的val。

原来:
v →address1 → Value[i=20] (原来的)
执行了之后(前面说的要搞清的那一步):
v →address2 → Value[i=15] (新new的)

原来的v---address1的指向断了而已,后续操作的是address2的内容。

最后一个输出的是原来的address1对应的Value的值,所以还是20,没变过。
gangsta
2015-07-13 12:40:28 +08:00
yuankui
2015-07-13 12:41:04 +08:00
要能区分什么时候传值,什么时候传引用~
这个道题就很好理解力.
sophie2805
2015-07-13 12:52:06 +08:00
@kalintw 懂了!

除了基础类型外,其他类型传的都是引用~

如果题目改一下,second方法有返回值,且返回值是v, first里面v = second(...)

这样的话,输出的就应该是
15 0
15
sophie2805
2015-07-13 12:52:30 +08:00
@BuilderQiu 懂了!

兄台解释的好粗犷,很受用
zhy
2015-07-13 12:55:36 +08:00
传引用就是传引用的值,类似一个指针
java只有pass by value
nozama
2015-07-13 13:17:39 +08:00
应该加个third, 考装箱拆箱
suikator
2015-07-13 13:29:43 +08:00
java方法参数传递只有唯一的一种形式,那就是传的所有东西都是拷贝。就算是传引用,传的也是引用的拷贝。但由于是引用,传之前和传之后都指向了同一个对象。

v=val 在方法体内改变了引用的指向之后,传之前和传之后就指向了不同的对象。

说错了你来打我呀
jeansfish
2015-07-13 13:47:00 +08:00
C#可以加个ref就是楼主想的了
lujiajing1126
2015-07-13 13:53:40 +08:00
java只有值传递

对象的值传递是通过对指针的复制做到的,所以你把复制的指针指向另一个对象,对之前的对象没有影响
codeyung
2015-07-13 16:43:20 +08:00
值传递
upupxjg
2015-07-13 16:54:09 +08:00
被代码格式折磨了半天,Format后发现原来真的考的是引用传递和值传递...
楼主不是单步了吗,看看new Value的时候 v的地址!
jziwenchen
2015-07-13 17:03:09 +08:00
尼玛 我以为多大的问题 这很基础呀! 对象是按引用传递的.
codeyung
2015-07-13 17:04:24 +08:00
这种问题 你那流程工具一搞比我们说的都清楚
jziwenchen
2015-07-13 17:05:16 +08:00
@BuilderQiu 额 不要用地址(很容易误解为内存的地址)去解释吧? 最好解释成别名.
vmskipper
2015-07-13 17:05:17 +08:00
我们公司最爱考这个题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/205293

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX