前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >短文:用字节码解析i++和++i的区别

短文:用字节码解析i++和++i的区别

作者头像
源码之路
发布2021-02-02 16:54:05
7700
发布2021-02-02 16:54:05
举报
文章被收录于专栏:源码之路源码之路

记得刚工作的时候被问i++是不是原子操作。初出茅庐答不上来,对java并发不了解。以此笔记缅怀自己的年轻。

看下面的代码

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        int i = 8;
        i = i++;
        System.out.println(i);
    }
}

打印的结果是啥? 答案是8. 换成下面的代码

代码语言:javascript
复制
public class Test {
    public static void main(String[] args) {
        int i = 8;
        i = ++i;
        System.out.println(i);
    }
}

答案是9。

是不是很无聊,相信很多人会回答,i++是先赋值再+1,++i是先+1再赋值。确实是这样,但是我总是想追根溯源,如何解释这个原则?

打开IDEA,下载一个jclasslib插件。

利用这个工具查看字节码文件,就是class文件。

右边就是显示这个类的class字节码信息,字节码其实是一堆二进制数据,当然,这些二进制数据按一定的规则存放,这个插件就是简单根据规则翻译了这个class文件,我们先看i=i++。 我们找到main方法对应的字节码

image.png

看到了吗,main方法的执行过程对应的jvm字节码指令就是

代码语言:javascript
复制
 0 bipush 8
 2 istore_1
 3 iload_1
 4 iinc 1 by 1
 7 istore_1
 8 getstatic #2 <java/lang/System.out>
11 iload_1
12 invokevirtual #3 <java/io/PrintStream.println>
15 return

首先解释一下什么是字节码指令,你写的java程序,JVM翻译成指令程序,指令程序最后再翻译成计算机认识的二进制程序。 毕竟计算机不认识你的java程序。因为它不是人。

要理解这个字节码,首先要明白,方法的执行就是操作栈帧,栈帧中包含了操作数栈和本地变量表这两个概念。 本地变量表,就是保存了方法的变量,比如第0位置的args参数,第1位置的i参数。操作数栈你可以理解对数据进行压栈出栈操作。 bipush 8就是把8压到操作数栈中。 istore_1就是操作数栈出栈,存到本地变量表的第1位置的i,就是代码中的i = 8; iload_1,就是变量表中第一个位置的i压栈到操作数栈顶,此时栈顶为8 iinc 1 by 1,就是变量表中第一个位置的i加1,那么变量表最终i=9 istore_1,又把栈顶的8存回了变量表中的i,那么i=8; 因为java代码中又赋值给了i。 所以最终打印8。

再看i=++i的字节码指令

代码语言:javascript
复制
 0 bipush 8   把8压到操作数栈中
 2 istore_1 操作数栈出栈,存到本地变量表的第1位置的i,就是代码中的i = 8;
 3 iinc 1 by 1 变量表中第一个位置的i加1,那么变量表最终i=9
 6 iload_1 变量表中第一个位置的i压栈到操作数栈顶,此时栈顶为9
 7 istore_1 又把栈顶的9存回了变量表中的i,那么i=9;
 8 getstatic #2 <java/lang/System.out>
11 iload_1
12 invokevirtual #3 <java/io/PrintStream.println>
15 return

关于i++,和++i的字节码指令JVM就是这么规定的。从表面上看就是上文说的,i=i++先赋值再加1,i=++i先加1再赋值。

曾经的那个面试官,你在哪儿,我来回答你当年那个问题,可能你并不知道也停留在表面吧。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档