黑马程序员技术交流社区

标题: 一个非常有趣的小问题 [打印本页]

作者: 李罡    时间: 2013-3-11 09:04
标题: 一个非常有趣的小问题
本帖最后由 李罡 于 2013-3-12 20:54 编辑

class  Add
{
public static void main(String[] args)
{
  int x=0;
  int z=0;
  for (int y=0;y<100 ;y++ )
  {
   x=x++;
   z=++z;
  }
  System.out.println("x="+x+",z="+z);
}
}


这个程序在java中运行出来是:x=0,z=100。
在VC中运行出来的是:x=100,z=100。
这是怎么回事?


作者: 曾钦    时间: 2013-3-11 09:14
因为在java中,x = x++ ,的执行顺序是,先把 x 赋值给 x ,再执行 x++;
所以不管执行多少次,x 还是 等于 0 ;
而 z=++z; 是先 ++z 也就是 z 的值已经改变了,然后赋值给 z .所以 最后 z = 100;{:soso_e113:}
作者: 李罡    时间: 2013-3-11 09:47
曾钦 发表于 2013-3-11 09:14
因为在java中,x = x++ ,的执行顺序是,先把 x 赋值给 x ,再执行 x++;
所以不管执行多少次,x 还是 等于  ...

呃,那vc的又怎么解释
作者: 曾钦    时间: 2013-3-11 09:51
李罡 发表于 2013-3-11 09:47
呃,那vc的又怎么解释

额,VC 方面不是很清楚,抱歉。。
不过我觉得应该是运行机制差异的问题。
在vc里面两个都是加完再赋值。(这个只是我的推测,正确与否还请楼主自己研究下哈。)
作者: 李罡    时间: 2013-3-11 14:31
曾钦 发表于 2013-3-11 09:51
额,VC 方面不是很清楚,抱歉。。
不过我觉得应该是运行机制差异的问题。
在vc里面两个都是加完再赋值。( ...

好吧,我也觉得是运行机制的问题。。。
作者: 陈丽莉    时间: 2013-3-12 13:55
如果还有问题,请继续追问,若没问题了,请将帖子分类改成【已解决】~
作者: HM张健    时间: 2013-3-12 17:29
曾钦 发表于 2013-3-11 09:14
因为在java中,x = x++ ,的执行顺序是,先把 x 赋值给 x ,再执行 x++;
所以不管执行多少次,x 还是 等于  ...

额 按你的过程 x先为0 再赋值给x   x值为0  然后执行x++  x++不就是x = x + 1么 最终x的值还是改变了啊
求解啊
作者: 许鑫星    时间: 2013-3-12 18:05
本帖最后由 许鑫星 于 2013-3-12 18:08 编辑

我觉得,在x赋值给x之后,就不是执行x++了,执行的应该是(x=x)++ 所以x值永远不会变化,这大概和运算符的优先级有关,在java中=的优先级要大于++,因此实际在自加的多半是那个赋值语句{:soso_e112:}
作者: 刘尚吉    时间: 2013-3-12 19:38
若增加一变量w,int w=0,然后x=w++;最后x=99,只有x=x++;自身赋值给自身时才这样。
作者: 薛飞    时间: 2013-3-12 20:26
本帖最后由 薛飞 于 2013-3-13 14:48 编辑
许鑫星 发表于 2013-3-12 18:05
我觉得,在x赋值给x之后,就不是执行x++了,执行的应该是(x=x)++ 所以x值永远不会变化,这大概和运算符的优 ...

x=x++;在虚拟机中的执行步骤是:1,先把x的值压入栈顶;2,再把x自增1;3,弹出栈顶值存入变量x中。具体查看在14楼的详细解释。
作者: 李罡    时间: 2013-3-12 20:54
HM张健 发表于 2013-3-12 17:29
额 按你的过程 x先为0 再赋值给x   x值为0  然后执行x++  x++不就是x = x + 1么 最终x的值还是改变了啊
...

我觉得运算过程是这样的:
第一步:x++的运算结果是0,
第二步:后面x的值自动加1,变成1。
第三步:x++的值赋给前面的x,前面x的值变为0
所以运算完以后x的值为0.

vc里估计是第二步和第三步反过来了。。。
作者: 陈丽莉    时间: 2013-3-12 21:53
这个只能说你没有及时来论坛看看,有问题也没有及时追问了~  没关系,最近技术分比之前好得多了,加油~
作者: 李罡    时间: 2013-3-12 23:23
陈丽莉 发表于 2013-3-12 21:53
这个只能说你没有及时来论坛看看,有问题也没有及时追问了~  没关系,最近技术分比之前好得多了,加油~ ...

一天都看视频去了。。。呵呵,等我学好了再来挣技术分~~~
作者: 薛飞    时间: 2013-3-13 14:37
在处理i=i++时,java虚拟机和VC的处理机制不同,利用javap -c Add命令进行反编译,得到下图,由此可分析出JVM的实际运行过程。

解释上图反编译出来的字节码指令内容:
0:把语句x=0中的常量0压入操作栈栈顶,此时栈顶为0;
1:弹出此时栈顶int型常量(即0)存储到位置为1的局部变量(即变量x)中,此时x=0;
2:把语句z=0中的常量0压入操作栈栈顶 ,此时栈顶为0;
3:弹出此时栈顶int型常量(即0)存储到位置为2的局部变量(即变量z)中,此时z=0;
4:把语句y=0中的常量0压入操作栈栈顶 ,此时栈顶为0;
5:弹出此时栈顶int型常量(即0)存储到位置为3的局部变量(即变量y)中,此时y=0;
6:从位置为3的局部变量(即变量y)中取出int类型的值装载到操作栈栈顶 ;
7:将byte类型的常量(即100)转换为int类型的常量 ,然后压入操作栈栈顶 ,此时栈顶为100;
9:条件转移指令,依次弹出栈顶两个元素,执行if(第一个元素>第二个元素)条件判断,如果判断结果为true则进行下一步(即第12步),否则转移到第28步。
12:从位置为1的局部变量(即变量i)中取出int类型的值(即0)装载到栈顶 ,此时栈顶为0;
13:变量1(即x)完成自增操作,即此时x=x+1;
16:把此时栈顶值(即0)存储到变量1中,此时x=0;
      (注意:此步操作结果实际覆盖掉了变量自增产生的值,正是此步导致了变量x最后的输出为x=0,这也正是有别VC的地方)
17:变量2(即z)完成自增操作,即此时z=z+1;
20:从位置为2的局部变量(即变量z)中取出int类型的值(即1)装载到栈顶  ,此时栈顶为1;
21:把此时栈顶值存入到变量2(即z)中,此时z=1;
22:变量3(即y)完成自增操作,此时y=y+1;
25:goto跳转到6步,进行循环;
28:得到结果,即为x=0,z=100。






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2