黑马程序员技术交流社区

标题: 看到输出结果 我凌乱了~ 菜鸟求指导~~555!!! [打印本页]

作者: 郭宁    时间: 2012-5-21 19:30
标题: 看到输出结果 我凌乱了~ 菜鸟求指导~~555!!!
  1. public class Test {
  2.         public static void main(String[] args)
  3.         {
  4.                 int j=0;
  5.                 for(int i = 0; i<100; i++)
  6.                 {
  7.                         j =j++;//我凌乱了~~  这个执行顺序是怎样啊?
  8.                 }
  9.                 System.out.println(j);
  10.         }

  11. }
复制代码
结果是  0 ~~~~~~
作者: Fc10232    时间: 2012-5-21 19:34
打个比方吧  a=b++,就相当于先把b的值赋给a,然后b++,你循环中的参数都没用到,所有对输出结果没影响   哈哈
作者: 胥江    时间: 2012-5-21 19:38
j =j++;//我凌乱了~~  这个执行顺序是怎样啊?

是这里出了问题,作用域没问题。
      改成 j =++j;//或者j=j+1都没有问题
是自增的问题
作者: Zhang_qian    时间: 2012-5-21 19:42
j=j++;的意思是先把j的值赋给j然后自身再加1的,如果是j=++j;那么结果就会是100它使先运算然后在赋值的。
作者: 云惟桉    时间: 2012-5-21 19:48
下面是用javap -c 来反编译成汇编,查操作过程。
j++反编译结果:
public static void main();
  Code:
   0:   iconst_0
   1:   istore_0
   2:   iload_0
   3:   iinc    0, 1
   6:   istore_0
   7:   return
}
++j 反编译结果:
public static void main();
  Code:
   0:   iconst_0
   1:   istore_0
   2:   iinc    0, 1
   5:   iload_0
   6:   istore_0
   7:   return
}
return前一句istore_0的意思是出栈。数据出栈也就意味着将最终结果赋值给左边变量。
因此重要的结论是:赋值操作总是在最后执行的!
所以并不要理所当然的按某些教材书上理解,什么++j在赋值前完成自增,j++在赋值后完成自增。这些都是不明确的结论。
实际是:
对于j=++j :先将j 的值自增然后压栈,最后赋值的时候出栈取出数值进行传递。
对于j=j++ :先将j 的值压栈,然后j++,最后把原来j 的值出栈进行赋值。因此还是原来的j 值。

不知道我这么说,楼主是否理解了。要记得赋值操作是最后的出栈操作。
希望能帮到你
作者: 杨梦宇    时间: 2012-5-21 19:51
java虚拟机的机制与C的不同,同样的程序在C语言中 如下:
  1. #include<stdio.h>
  2. void main()
  3. {
  4.         int i; int j=0;
  5.         for(i=0;i<100;i++)
  6.            j=j++;
  7. printf("%d",j);
  8. }
复制代码
结果为100
我查阅了有关资料 得出下面的回答
What happens is that the initial value of x is stored in a temporary register, then x is incremented, then the value stored in the register is asigned to the left hand side of the expression, in this case the LHS is x so x gets its original value.
int x = 0;
x = x++;
Steps:
1 initial value of x is stored in temp register. So temp = 0.
2 x is incremented. x = 2 and temp = 0.
3 the value of the temp register is assigned to the LHS. x = 0

我翻译下,
程序运行中,x的起始值被存在了一个暂时的寄存器中,然后那个原始的x自增1,然后寄存器中的x值给了表达式的等号左边,所以x的值总是原始的。

如果楼主想进一步研究,可以借助反编译,有下面的链接
http://zhidao.baidu.com/question/392618024.html
作者: 郭宁    时间: 2012-5-21 20:30
云惟桉 发表于 2012-5-21 19:48
下面是用javap -c 来反编译成汇编,查操作过程。
j++反编译结果:
public static void main();

按你的思路想 感觉是那么回事,但还是有些迷糊,不清楚为什么这样紫~
引用Fc10232的“打比方 a = b++” 能给我详细说一下 整个赋值过程么?
作者: 云惟桉    时间: 2012-5-21 20:37
郭宁 发表于 2012-5-21 20:30
按你的思路想 感觉是那么回事,但还是有些迷糊,不清楚为什么这样紫~
引用Fc10232的“打比方 a = b++”  ...

嗯,楼主可以这么理解:(假设b=0)
step 1:  b的值压栈,栈内为0;
step 2:  b++,此时b=1;
step 3: 数据出栈,0出栈,赋值,a=0;
这样楼主理解吗?
不理解可以使用输出语句,输出a和b,可能对理解有点帮助
作者: 郭宁    时间: 2012-5-21 20:50
云惟桉 发表于 2012-5-21 20:37
嗯,楼主可以这么理解:(假设b=0)
step 1:  b的值压栈,栈内为0;
step 2:  b++,此时b=1;

按你的意思   j=j++  这种情况 j 在运算的过程  一直是被 置为 1  又 置为 0 这样循环的么?

作者: 云惟桉    时间: 2012-5-21 20:54
郭宁 发表于 2012-5-21 20:50
按你的意思   j=j++  这种情况 j 在运算的过程  一直是被 置为 1  又 置为 0 这样循环的么?
  ...

Excellent!!!说明楼主已经理解了!
作者: 龚龙    时间: 2012-5-21 21:55
郭宁 发表于 2012-5-21 20:50
按你的意思   j=j++  这种情况 j 在运算的过程  一直是被 置为 1  又 置为 0 这样循环的么?
  ...

j=0
for..{
j=j++
}
每次循环的时候,先进行赋值运算j=0,再进行自增运算++,但是此时并没有任何变量记住这个自增的后的变量,所以下次循环的时候j还是0,如此循环100次,最终还是j还是0.

作者: 金鑫    时间: 2012-5-21 22:48
j=j++;
System.out.println(j);
实际上是先输出j,然后再进行++运算。无论你的for循环是什么样的,他输出的永远是j的初始值0;
把j++换成++j,最终结果就是100。因为他是先进行++运算,然后将运算完的结果再进行输出;
作者: 袁錦泰    时间: 2012-5-21 22:54
云惟桉 发表于 2012-5-21 19:48
下面是用javap -c 来反编译成汇编,查操作过程。
j++反编译结果:
public static void main();

哥們,請教個問題,你上面的反編譯結果是怎麼的出來的?
作者: 云惟桉    时间: 2012-5-22 00:47
袁錦泰 发表于 2012-5-21 22:54
哥們,請教個問題,你上面的反編譯結果是怎麼的出來的?

我知道的有两种方式,再多的就不知道了
我用的是【javap -c 类名 】的命令,实际上这是一个反汇编过程。
另外一种方式是在eclipse里装jadclipse。
我对这个不是很在行,而且有些反汇编的指令我看不懂,是舍友帮忙看的。
希望能帮助你~
作者: 袁錦泰    时间: 2012-5-22 10:51
云惟桉 发表于 2012-5-22 00:47
我知道的有两种方式,再多的就不知道了
我用的是【javap -c 类名 】的命令,实际上这是一个反汇编过程。
...

非常感謝!! 我也看不懂,想和你取取經,這東西似乎對程序分析非常有幫助...
作者: 钟成军    时间: 2012-5-22 11:41
j的值没有变化,如果++在前,结果就是100了,因为++在后,所以在将j赋给j后,j 再自增的值没有赋给谁,仍为0
作者: 云惟桉    时间: 2012-5-22 11:43
袁錦泰 发表于 2012-5-22 10:51
非常感謝!! 我也看不懂,想和你取取經,這東西似乎對程序分析非常有幫助...

嗯,貌似看懂了这个对编程很有帮助。不过先把基础打好最要紧,现在最担心就是基础不牢靠,做事时事倍功半。要盖高楼,还是需要稳固的地基啊~
作者: 袁錦泰    时间: 2012-5-22 11:53
云惟桉 发表于 2012-5-22 11:43
嗯,貌似看懂了这个对编程很有帮助。不过先把基础打好最要紧,现在最担心就是基础不牢靠,做事时事倍功半 ...

哥们儿留个QQ号...
作者: 云惟桉    时间: 2012-5-22 11:54
袁錦泰 发表于 2012-5-22 11:53
哥们儿留个QQ号...

1121411378
作者: 袁錦泰    时间: 2012-5-22 11:57
本帖最后由 袁錦泰 于 2012-5-22 12:07 编辑
云惟桉 发表于 2012-5-22 11:54
1121411378

826288180 你拒绝被添加好友....
作者: 闾丘日月    时间: 2012-5-22 15:24
果然反编译才是王道啊,编译器底层怎么干的,各个厂商估计都不一样,所以我们写代码应该尽量避免写出这种代码。。不过作为学习真是不错,受教了。
作者: 黑马-李勇    时间: 2012-5-22 16:34
不明白为什么不写j++,搞出这多问题。
作者: 何旭栋    时间: 2012-5-22 19:29
本帖最后由 何旭栋 于 2012-5-22 19:51 编辑
  1. class Demo
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 int k = 3;
  6.                                 k += k++;
  7.                                 System.out.println(k);
  8.                 }
  9. }
复制代码
输出结果为6,而不是4或者7,可见赋值的最终结果参考左边。




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