在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++是不等价的!!!

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

为什么i=i++后,i的值不变(深入解析)的更多相关文章

  1. ListView与.FindControl()方法的简单练习 #2 -- ItemUpdting事件中抓取「修改后」的值

    原文出處  http://www.dotblogs.com.tw/mis2000lab/archive/2013/06/24/listview_itemupdating_findcontrol_201 ...

  2. Sql示例说明如何分组后求中间值--【叶子】

    原文:Sql示例说明如何分组后求中间值--[叶子] 这里所谓的分组后求中间值是个什么概念呢? 我举个例子来说明一下: 假设我们现在有下面这样一个表: type        name price -- ...

  3. 后端model传入前端JSP页面中的值判断后再取值

    所遇到的问题后端model传入前端JSP页面中的值通过foreach循环内要满足条件才能取值给Div中,我们知道jsp页面中可以直接用EL表达式取值,格式就是${"model中传来的数据&q ...

  4. MySQL 如何在一个语句中更新一个数值后返回该值 -- 自增长种子竞态问题处理

    什么是竞态问题? 假设有一个计数器,首先当前值自增长,然后获取到自增长之后的当前值.自增长后的值有可能被有些操作用来当做唯一性标识,因此并发的操作不能允许取得相同的值. 为什么不能使用使用UPDATE ...

  5. python执行系统命令后获取返回值的几种方式集合

    python执行系统命令后获取返回值的几种方式集合 今天小编就为大家分享一篇python执行系统命令后获取返回值的几种方式集合,具有很好的参考价值,希望对大家有所帮助.一起跟随小编过来看看吧 第一种情 ...

  6. c++ xml 解析“后直接跟值问题

    c++ xml库相关 要解析内容: <ITEM name="SLSJ"head="SLSJ"/> 代码: GetNodeAttri(subnodes ...

  7. [BS-00] const限定常量或者变量(初次赋值后),其值不允许被改变

    CONST(C中的CONST) const是一个C语言(ANSI C)的关键字,它限定一个变量不允许被改变,产生静态作用.使用const在一定程度上可以提高程序的安全性和可靠性.另外,在观看别人代码的 ...

  8. EDMX更新实体后出现键值映射问题

    近期做项目的EF改版时,在DB(ORACLE)中的表里添加一个新的PK,去除原有的PK. 在DB已添加完成操作,但这时在EDMX里进行从DB更新到EF里,更新完成后就发生如下错误提示: Error 6 ...

  9. [Shell]Shell调用并获取执行jar包后的返回值

    ----------------------------------------------------------------- 原创博文,如需转载请注明出处! 博主:疲惫的豆豆 链接:http:/ ...

  10. vue 解决双向绑定中 父组件传值给子组件后 父组件值也跟着变化的问题

    说明: 近日开发中碰见一个很诡异的问题,  父组件动态的修改对象 data 中的值, 然后将这个对象 data 传给子组件, 子组件拿到后将 data 中的值 乘以 100 ,发现父组件中的值也跟着变 ...

随机推荐

  1. ubuntu terminal copy paste

    copy: ctrl + insert paste: shift + insert

  2. MySQL入门很简单: 12 MYSQL 用户管理

    1. 权限表 安装MySQL会自动安装一个名为mysql的数据库,存储权限表: user表, db表,host表,table_priv表,columns_priv表,proc_priv表等. 1)us ...

  3. 转载:手把手教你搭建 vue 环境

    以下内容转自: https://segmentfault.com/a/1190000008922234 第一步 node环境安装 1.1 如果本机没有安装node运行环境,请下载node 安装包进行安 ...

  4. 单调队列 poj2823,fzu1894

    题目链接:http://poj.org/problem?id=2823 用RMQ超时了,我想应该是不会的,看discuss说,之前RMQ过了. 维护两个单调队列. 单调递减的队列,每插入一个时: 超过 ...

  5. 【洛谷P1379】八数码难题(广搜、A*)

    八数码难题 题目描述 一.广搜: 首先要考虑用什么存每一个状态 显然每个状态都用一个矩阵存是很麻烦的. 我们可以考虑将一个3*3的矩阵用一个字符串或long long 存. 每次扩展时再转化为矩阵. ...

  6. No such file or directory 8356:error:02001003:system library:fopen:No such process:crypto\bio\bss_file.c:7 4:fopen

    使用OpenSSL生成证书,构建根证书前,需要构建随机数文件(.rand),命令如下: openssl rand - 报错如下: OpenSSL> rand - Can't open priva ...

  7. 项目部署到自己的IIS上

    一般我们只能在本机上才可以开到我们的项目,这个是不需要连网的 如果想让我们的项目在网站中打开,别人也可以看到,就需要把我们的项目部署到服务器上了,输入IP就可以看到我们的项目 发布项目 然后发布网站 ...

  8. C#流程控制语句

    C#流程控制语句 一.选择语句 当程序中需要进行两个或两个以上的选择时,可以根据条件的判断来选择将要执行的一组语句. ?if语句 ?switch语句 二.循环语句 循环语句是对一个程序模块进行的重复操 ...

  9. css3 子元素的的应用 注意点

    已经第二次犯错误,不允许有下次 <ul class="ul"> <li> <a>哈哈</a> </li> <li& ...

  10. django中的forms组件(权限信息校验,增删改查)

    1.用处 1.用户请求数据验证 2.自动生成错误信息 3.打包用户提交的正确信息 4.如果其中有一个错误了,其他的正确,则保留上次输入的内容 5.自动创建input标签并可以设置样式 6.基于form ...