黑马程序员技术交流社区
标题: 看到输出结果 我凌乱了~ 菜鸟求指导~~555!!! [打印本页]
作者: 郭宁 时间: 2012-5-21 19:30
标题: 看到输出结果 我凌乱了~ 菜鸟求指导~~555!!!
- public class Test {
- public static void main(String[] args)
- {
- int j=0;
- for(int i = 0; i<100; i++)
- {
- j =j++;//我凌乱了~~ 这个执行顺序是怎样啊?
- }
- System.out.println(j);
- }
- }
复制代码 结果是 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语言中 如下:- #include<stdio.h>
- void main()
- {
- int i; int j=0;
- for(i=0;i<100;i++)
- j=j++;
- printf("%d",j);
- }
复制代码 结果为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 编辑
- class Demo
- {
- public static void main(String[] args)
- {
- int k = 3;
- k += k++;
- System.out.println(k);
- }
- }
复制代码 输出结果为6,而不是4或者7,可见赋值的最终结果参考左边。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) |
黑马程序员IT技术论坛 X3.2 |