问:
int i = 0;
i = ++i; i的值是多少?毫无疑问,i = 1;但是,i = ++i;这条语句对i进行了两次赋值:第一次,i自增,此时i=1;第二次,将++i的表达式的值(也就是1)赋给i。我们通过字节码来分析一下这段代码的执行过程:
//int i = 0;的字节码
0:iconst_0 //将int型0推送至栈顶
1:istore_1 //将栈顶值(0)存入局部变量表中索引为1的地方(也就是i)
// i = ++i;的字节码
2:innc 1,1 //在局部变量表中索引为1的变量加1,此时i=1;
3:iload_1 //索引为1的变量值存入栈顶
4:istore_1 //将栈顶值存入索引为1的变量中
理解了上面的代码后,再考虑这样两行代码:
int i = 0;
i = i++; 这两条代码执行完成后,i的值是多少?答案是0。稍加思考,就会觉得这个结果并不是太意外,这两句代码的执行过程是这样的:
1))定义整型局部变量i,初始值为0;
2)JVM执行i++计算,该表达式的值为0;
3) i自增,i此时为1;
4)将i++表达式的值赋给i,i++表达式的值是0,所以赋值后,i = 0;
5)计算完毕,i = 0。
上面的每一步都不会让我们感到意外,为了更加清晰的说明问题,上面两行代码的等价代码如下:
int i = 0;
int tmp = 0; //对应分析中的第(2)步,也就是i++表达式的值
i++; //分析中的第(3)步
i = tmp; //分析中的第(4)步
我们也从字节码看看这两条语句的执行过程:
//int i = 0;的字节码
0:iconst_0 //将int型0推送至栈顶,此时栈中的内容:[0]
1:istore_1 //将栈顶值(0)存入局部变量表中索引为1的地方(也就是i),i = 0;栈中的内容:[ ]
// i = i++;的字节码
2:iload_1 //索引为1的变量值存入栈顶,也就是i++表达式的值(0)存入栈顶,此时栈中的内容:[0]
3:innc 1,1 //在局部变量表中索引为1的变量加1,此时i=1;栈中的内容:[0]
4:istore_1 //将栈顶值(0)存入索引为1的变量中,i=0;栈中的内容:[ ]
从字节码中,我们可以看到:JVM首先把i++表达式的值存入到操作数栈中,也就是栈中保存着i = i++右半部的值(表达式i++,也就是0);然后把=右边的表达式计算完毕;最后将表达式i++的值赋给i(栈顶元素出栈,赋给i)。注意,i++是一个表达式,这个表达式的值是0。
这样的讨论其实是没有意义的,不要在一个表达式中,对同一个变量多次赋值!
参考资料:http://www.ticmy.com/?p=43(写这篇博客主要是为了加深自己的理解)
|