看一些JAVA基础题的时候,经常看到这个问题,很多人的解释是:i++最快,i+=1其次,i=i+1最慢。下面通过Sun JDK编译出来的字节码验证一下这个问题。

为了让编译出来的字节码便于阅读,将这三个表达式分别写在一个方法里面:

     private void a(){
int i=0;
i += 1;
} private void b(){
int i=0;
i++;
} private void c(){
int i=0;
i=i+1;
}

编译之后(SUN JDK1.7),再看编译出来的字节码(直接把.class文件用IDE打开,或者用javap -v -p classFileName命令):

// Method descriptor #6 ()V
// Stack: 1, Locals: 2
private void a();
0 iconst_0
1 istore_1 [i]
2 iinc 1 1 [i]
5 return
Line numbers:
[pc: 0, line: 15]
[pc: 2, line: 16]
[pc: 5, line: 17]
Local variable table:
[pc: 0, pc: 6] local: this index: 0 type: com.leo.javabasis.Add
[pc: 2, pc: 6] local: i index: 1 type: int // Method descriptor #6 ()V
// Stack: 1, Locals: 2
private void b();
0 iconst_0
1 istore_1 [i]
2 iinc 1 1 [i]
5 return
Line numbers:
[pc: 0, line: 20]
[pc: 2, line: 21]
[pc: 5, line: 22]
Local variable table:
[pc: 0, pc: 6] local: this index: 0 type: com.leo.javabasis.Add
[pc: 2, pc: 6] local: i index: 1 type: int // Method descriptor #6 ()V
// Stack: 1, Locals: 2
private void c();
0 iconst_0
1 istore_1 [i]
2 iinc 1 1 [i]
5 return
Line numbers:
[pc: 0, line: 25]
[pc: 2, line: 26]
[pc: 5, line: 27]
Local variable table:
[pc: 0, pc: 6] local: this index: 0 type: com.leo.javabasis.Add
[pc: 2, pc: 6] local: i index: 1 type: int

这三个方法的字节码是一样的(除了行号),先稍微解释一下这段字节码指令:

iconst_0 //整数常量0入栈
istore_1 //将栈上的值出栈,保存到序号为1的局部变量(也就是i)
iinc 1 1 //将序号为1的局部变量增加1,此指令语法为iinc index const。
是不是SUN JDK在某一个版本之前是没有对这个问题进行优化?找了一个能用的SUN JDK 1.3再试了一下(1.1, 1.2跑不动了),编译出来的结果,方法a、b的字节码和1.7下是一样的。但是c的就不一样了:
Method void c()
0 iconst_0
1 istore_1
2 iload_1
3 iconst_1
4 iadd
5 istore_1
6 return

指令行2-5的作用分别是:

iload_1 //将序号为1的局部整数变量入栈
iconst_1 //整数常量1入栈
iadd //使用栈上的两个整数值出栈进行加法运算,将结果入栈
istore_1 //将栈上的整数值保存到序号为1的局部变量
这种方式同样达到了相加的目的,但是相比直接iinc指令,还是绕了很多,效率自然不会好。

由此看来,在某一个版本之后,编译器是对这个问题进行了优化。关于谁的效率好的问题,在现在的SUN JDK版本中已经没有差别了(即使是使用1.7的JDK编译出的1.3JRE兼容的字节码,方法c也是优化过的),
但是曾经某个时代确实是有差别的。

JAVA的i++, i+=1, i=i+1有区别吗?的更多相关文章

  1. Java中集合List,Map和Set的区别

    Java中集合List,Map和Set的区别 1.List和Set的父接口是Collection,而Map不是 2.List中的元素是有序的,可以重复的 3.Map是Key-Value映射关系,且Ke ...

  2. Java中的“==操作符”和equals方法有什么区别

    Java中的"=="和equals方法究竟有什么区别? 1.==操作符 "=="操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的 ...

  3. 列举两种不同类型的Java标识注释,并解释它们之间的区别。

    列举两种不同类型的Java标识注释,并解释它们之间的区别.

  4. java多线程之yield,join,wait,sleep的区别

    Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...

  5. JAVA基础2---深度解析A++和++A的区别

    我们都知道JAVA中A++和++A在用法上的区别,都是自增,A++是先取值再自增,++A是先自增再取值,那么为什么会是这样的呢? 1.关于A++和++A的区别,下面的来看个例子: public cla ...

  6. Java Web开发和Python Web开发之间的区别

    今天的文章讨论了Java Web开发和Python Web开发之间的区别.我不鼓励我们在这里从Java Web迁移到Python Web开发.我只是想谈谈我的感受.它不一定适合所有情况,仅供我们参考. ...

  7. 杂项-Java:jar 包与 war 包介绍与区别

    ylbtech-杂项-Java:jar 包与 war 包介绍与区别 1.返回顶部 1. 做Java开发,jar包和war包接触的挺多的,有必要对它们做一个深入的了解,特总结整理如下: 1.jar包的介 ...

  8. “全栈2019”Java第一百一十章:局部内部类与匿名内部类区别详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. [转]Java五个最常用的集合类之间的区别和联系

    Map<String, ?>只能是只读模式,不能增加,因为增加的时候不知道该写入什么类型的值:Map<String, Object>可以读和写,只要是所有Object类的子类都 ...

  10. java中,return和return null有什么区别吗?

    java中,return和return null有什么区别吗? 最大的区别:return;方法的返回值必须是void!return null;方法的返回值必须不是 原始数据类型(封装类除过)和void ...

随机推荐

  1. java程序设计之反弹高度

    题目:一球从100米高度自由落下,每次落地后反跳回原高度的一半:再落下,求它在第10次落地时,共经过多少米?第10次反弹多高? 代码: public class highe { double high ...

  2. ReactNative新手学习之路06滚动更新ListView数据的小示例

    本节带领大家学习使用ListView 做一个常用的滚动更新数据示例: 知识点: initialListSize={200} 第一次加载多少数据行 onEndReached={this.onEndRea ...

  3. JS中判断鼠标按键的问题

    JS中判断鼠标按键的问题.IE左键是 window.event.button = 1右键是 window.event.button = 2中键是 window.event.button = 4没有按键 ...

  4. WPF之Binding

    Binding就是将数据源和目标联系起来,一般来说可以是将逻辑层对象和UI层的控件对象相关联. 有连接就有通道,就可以在通道上建立相应的验证等关卡来验证数据有效性,或是其它处理工作:同时它也支持对数据 ...

  5. c#串口通信类代码可以直接调用

    文章首发于浩瀚先森博客 直接上代码 public struct SerialPara { private string portName; public string PortNameSetGet { ...

  6. 《JavaScript高级程序设计》 - 读书笔记 - 第4章 变量、作用域和内存问题

    4.1 基本类型和引用类型的值 JavaScript变量是松散类型的,它只是保存特定值的一个名字而已. ECMAScript变量包含两种数据类型的值:基本类型值和引用类型值.基本类型值指的是简单的数据 ...

  7. FPGA与simulink联合实时环路系列—开篇

    FPGA与simulink联合实时环路系列—开篇 作为网络上第一个开源此技术,笔者迫不及待地想将此技术分享出来,希望大家多多支持.笔者从2011年接触FPGA以来,从各个方面使用FPGA,无论是控制. ...

  8. SQL数据库分配权限

    打开SQL-Server管理工具->安全性->登陆名->右键(新建登陆名) 输入相应的信息(这里要去掉强制实施密码策略,强制密码过期,否则用户在下次登录时必须修改密码) 用户映射-& ...

  9. 利用ucenter整合discuz数据

    由于项目需要,需要用到discuz论坛用户的数据,所以想到利用ucenter获取数据.以下为整合ucenter的过程. 1.首先你需要下载官方demo:http://faq.comsenz.com/l ...

  10. MySQL多配置方式的多实例的部署

    安装MySQL需要注意的事项: 选择MySQL的版本的建议: 1)稳定版:选择开源的社区版的稳定版GA版本 2)选择MySQL数据库GA版本发布后六个月以后得GA版本 3)选择发布版本前后几个月没有大 ...