在Java中,运行以下代码:

         int i=10;
i=i++;
System.out.println(i);

得到的结果仍然为10,为什么呢?理论上,运算的过程不应该是i首先把10取出来,赋值给i,然后i再自增1,结果不该是11吗?

原因还是要从反编译得到的汇编源码看起。在cmd窗口,输入命令javap -c Demo(Demo是class的文件名),可以得到反编译的汇编源码,

下面我们一步步来,先将两行简单的代码反编译一下。

         int i=10;
int j=9;

上述两行代码的反编译结果是

        0: bipush        10      //将常量10压入操作数栈 
2: istore_1 //将操作数栈顶元素(10)弹出,存入局部变量位置1处
3: bipush 9 //将常量9压入操作数栈
5: istore_2 //将操作数栈顶元素(9)弹出,存入局部变量位置2处
6: return

上下代码可以很简单的对应起来,可以初步看出,赋值语句在汇编其实是有两步,第一步压栈(操作数栈),第二部(出栈并存储至局部变量处)。

为了进行验证,再多加一行代码,如下

         int i=10;
int j=9;
j=i;

同样,反编译看汇编如下:

        0: bipush        10
2: istore_1
3: bipush 9
5: istore_2
6: iload_1
7: istore_2
8: return

很明显的可以看到,j=i这一句,并不是直接把局部变量位置1的值赋值给局部变量2,而是先压入操作数栈,再弹出存储在局部变量位置2处!

下面我们把最开头的i=i++进行一下反编译,得到的结果如下。

 public class Demo {
public Demo();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return public static void main(java.lang.String[]);
Code:
0: bipush 10 //将常量10压入操作数栈
2: istore_1 //将操作数的栈顶元素(10)出栈,存入局部变量表1的位置处(这两句话完成了i=10的赋值操作)
: iload_1 //将局部变量表1位置的值压入操作数栈
4: iinc 1, 1 //局部变量表1位置的值自增1
: istore_1            //重新将操作数栈顶的值(10)出栈存入局部变量表1的位置处
8: return
}

只需要从第10行看起就可以了。

可以很明显的看到,自增过程是发生在压栈和出栈中间,所以最后出栈的值会把自增的结果覆盖,导致自增其实是没有作用的。

其实还可以得出一个结论,就是自增和普通的运算的步骤是不同的。自增是直接在局部变量区加1,而运算要进行压栈和出栈操作。

为了验证这句最关键的话,我们把下面代码进行一次反编译。

         int i=10;
i++;
i=i+1;

得到的反编译结果如下:

        0: bipush        10
2: istore_1
3: iinc 1, 1
6: iload_1
7: iconst_1
8: iadd
9: istore_1
10: return

这下很明显了,i++就只有一句话,iinc    1,1,代表在局部变量位置1处的值自增1,而i=i+1则是先把局部变量1位置处的值压栈,再把常量1压栈,再相加出栈,一共四句话!

因此,从内存的角度来看,i=i+1和i++是不同的,也就是说:

i=i++这句话与i=i=i++是不等价的!!!

明白了这个道理,我想再看这个题应该就没有那么恶心了!

最新文章

  1. DirectShow
  2. Oracle经典SQL
  3. linux的帮助信息获取以及man章节的划分
  4. Oracle 11g 修改字符集 为 ZHS16GBK
  5. H3C IRF mad检测
  6. sessionFactory
  7. apple-touch-icon,shortcut icon和icon的区别(手机站发送到手机桌面图标自定义)
  8. emacs 操作集锦
  9. java获取数据库的所有列名和对应的数据库类型
  10. 可扩展的listview--Expandablelistview
  11. ecshop标签
  12. basicAnimation移动图形
  13. jQuery中ready与load事件的区别
  14. UVA 1623 Enter The Dragon
  15. hdu_5787_K-wolf Number(数位DP)
  16. elasticsearch 集群基本概念
  17. 单片机课程设计——《基于AT89S52单片机和DS1302时钟芯片的电子时钟(可蓝牙校准)》
  18. 使用.net 自建短链接(短网址)
  19. python用户管理系统
  20. freemarker的classic_compatible设置,解决报空错误

热门文章

  1. 解决频繁自动弹出“QQ拼音升级程序”,可使用旧版QQ输入法
  2. April 8 2017 Week 14 Saturday
  3. java常用输出技巧,debug
  4. Centos 5.2下安装多个mysql数据库
  5. Mac安装protobuf 流程
  6. centos7 kvm安装使用
  7. 激活SQLPrompt7.4及以上版本
  8. AngularJS THML DOM
  9. 11、SpringBoot------定时任务
  10. Xcode 中 pch 文件配置 - iOS