原文出处: Ticmy

1
2
int i = 0;
i = i++;

结果还是0
为什么?

程序的执行顺序是这样的:因为++在后面,所以先使用i,“使用”的含义就是i++这个表达式的值是0,但是并没有做赋值操作,它在整个语句的最后才做赋值,也就是说在做了++操作后再赋值的,所以最终结果还是0

让我们看的更清晰点:

1
2
int i = 0;//这个没什么说的
i = i++;//等效于下面的语句:
1
2
3
int temp = i;//这个temp就是i++这个表达式的值
i++; //i自增
i = temp;//最终,将表达式的值赋值给i

这是java里的实现,当然在其他的语言如c或是c++中可能并不是这么处理的,每种语言都有各自的理由去做相应的处理。

这警示我们:不要在单个的表达式中对相同的变量赋值超过一次

让我们从字节码层次看一看,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
public class Test {
 
    public static void main(String... args) {
 
        int i = 0;
 
        i = i++;
 
        System.out.println(i);
 
    }
}

使用javac编译后再使用javap -c Test反编译这个类查看它的字节码,如下(只摘取main方法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public static void main(java.lang.String[]);
 
Code:
 
0: iconst_0
 
1: istore_1
 
2: iload_1
 
3: iinc 1, 1
 
6: istore_1
 
7: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
 
10: iload_1
 
11: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
 
14: return

这里,我从第0行开始分析(分析中【】表示栈,栈的底端在左边,顶端在右边):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
0:将常数0压入栈,栈内容:【0
 
1:将栈顶的元素弹出,也就是0,保存到局部变量区索引为为1(也就是变量i)的地方。栈内容:【】
 
2:将局部变量区索引为1(也就是变量i)的值压入栈,栈内容:【0
 
3:将局部变量区索引为1(也就是常量i)的值加一,此时局部变量区索引为1的值(也就是i的值)是1。栈内容:【0
 
6:将栈顶元素弹出,保存到局部变量区索引为1(也就是i)的地方,此时i又变成了0。栈内容:【】
 
7:获取常量池中索引为2所表示的类变量,也就是System.out。栈元素:【】
 
10:将局部变量区索引为1的值(也就是i)压入栈。栈元素:【0
 
11:调用常量池索引为3的方法,也就是System.out.println
 
14:返回main方法

java中i=i++字节码分析的更多相关文章

  1. Java中HashMap的源码分析

    先来回顾一下Map类中常用实现类的区别: HashMap:底层实现是哈希表+链表,在JDK8中,当链表长度大于8时转换为红黑树,线程不安全,效率高,允许key或value为null HashTable ...

  2. 通过字节码分析java中的switch语句

    在一次做题中遇到了switch的问题,由于对switch执行顺序的不了解,在这里简单的通过字节码的方式理解一下switch执行顺序(题目如下): public class Ag{ static pub ...

  3. Java并发编程原理与实战八:产生线程安全性问题原因(javap字节码分析)

    前面我们说到多线程带来的风险,其中一个很重要的就是安全性,因为其重要性因此,放到本章来进行讲解,那么线程安全性问题产生的原因,我们这节将从底层字节码来进行分析. 一.问题引出 先看一段代码 packa ...

  4. Java字节码分析

    目录 Java字节码分析 查看字节码详细内容 javap 实例分析 Java字节码分析 对于源码的效率,但从源码来看有时无法分析出准确的结果,因为不同的编译器版本可能会将相同的源码编译成不同的字节码, ...

  5. JVM-String比较-字节码分析

    一道String字符串比较问题引发的字节码分析 public class a { public static void main(String[] args)throws Exception{ } p ...

  6. 通过字节码分析this关键字以及异常表的重要作用

    在之前的字节码分析中缺少对异常的介绍,这次主要来对字节码异常表相关的东东进行一个学习,下面先来编写一个相关异常的小程序: 接着编译来看用javap -verbose来查看一下它的字节码信息: xion ...

  7. java线程池ThreadPoolExector源码分析

    java线程池ThreadPoolExector源码分析 今天研究了下ThreadPoolExector源码,大致上总结了以下几点跟大家分享下: 一.ThreadPoolExector几个主要变量 先 ...

  8. 死磕 java集合之DelayQueue源码分析

    问题 (1)DelayQueue是阻塞队列吗? (2)DelayQueue的实现方式? (3)DelayQueue主要用于什么场景? 简介 DelayQueue是java并发包下的延时阻塞队列,常用于 ...

  9. 死磕 java集合之PriorityBlockingQueue源码分析

    问题 (1)PriorityBlockingQueue的实现方式? (2)PriorityBlockingQueue是否需要扩容? (3)PriorityBlockingQueue是怎么控制并发安全的 ...

随机推荐

  1. 嵌入式Linux驱动学习之路(六)u-boot启动内核

    内核启动是需要必要的启动参数.不能开机自动完全从0开始启动,需要uboot帮助内核实现重定位并提供参数. 首先,uboo会从Kernel分区中读取bootcmd环境变量,根据环境变量可自动启动. 分区 ...

  2. javascript获取元素的方法[xyyit]

    1. javascript默认的方法: <div id=”div_id” class=”div_class” name=”div_name”></div> //1. 根据id ...

  3. Web安全测试之跨站请求伪造(CSRF)篇

    跨站请求伪造(即CSRF)被Web安全界称为诸多漏洞中“沉睡的巨人”,其威胁程度由此“美誉”便可见一斑.本文将简单介绍该漏洞,并详细说明造成这种漏洞的原因所在,以及针对该漏洞的黑盒测试与灰盒子测试具体 ...

  4. Xcode基本操作

    2.偏好设置 通过“command+,”快捷键或”Xcode|Preferences”菜单呼出偏好设置. (1)主题及字体(Preferences->Fonts & Colors) 选中 ...

  5. COGS 2. 旅行计划

    2. 旅行计划 ★☆   输入文件:djs.in   输出文件:djs.out   简单对比时间限制:3 s   内存限制:128 MB 过暑假了,阿杜准备出行旅游,他已经查到了某些城市的两两之间的距 ...

  6. BZOJ 4717 改装

    Description [题目背景] 小Q最近喜欢上了一款游戏,名为<舰队connection>,在游戏中,小Q指挥强大的舰队南征北战,从而成为了一名dalao.在游戏中,不仅船只能力很重 ...

  7. usb驱动开发17之设备生命线

    拜会完了山头的几位大哥,还记得我们从哪里来要到哪里去吗?时刻不能忘记自身的使命啊.我们是从usb_submit_urb()最后的那个遗留问题usb_hcd_submit_urb()函数一路走来,现在就 ...

  8. 傅盛:如何快慢“炼”金山?(转)

    原文地址:http://www.huxiu.com/article/16052/1.html 一直以来,金山都不是一家"大公司",从前不是,现在也不是. 能够掰着指头数完腾讯六大事 ...

  9. 毫米转换为PX

    公式:毫米数/25.4*你的电脑的DPI,win7 DPI  100%缩放为96,125%为120,150%为144,200%为192 象素数 / DPI = 英寸数 英寸数 * 25.4 = 毫米数

  10. 离线安装 Cloudera ( CDH 5.x )

    要配置生产环境前,最好严格按照官方文档/说明配置环境.比如,官方说这个安装包用于RETHAT6, CENTOS6,那就要装到6的版本下,不然很容易出现各种各样的错. 配置这个CDH5我入了很多坑,最重 ...