看一些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 object

    1.toString 把对象变成字符串  对于一个引用型变量toString写不写都是一样的 2.equals()  比较两个对象的引用是否一样. 3. public class EqualsTest ...

  2. jquery 里面对数组去重操作-unique

    js: var yearArray = new Array(2009, 2009, 2010, 2010, 2009, 2010); $.unique(yearArray); alert(yearAr ...

  3. CSS选定第k个元素

    <!DOCTYPE html> <html> <head> <title></title> <style type="tex ...

  4. C语言与内存模型初探

    #include<stdio.h> #include<string.h> int main(){ long long int a = 2<<30; char str ...

  5. [转]Hibernate延迟加载与opensessioninviewFilter

    原文地址:http://blog.csdn.net/a19881029/article/details/7916702 hibernate延迟加载: 一个person对应多个school,使用hibe ...

  6. 【Ural】1519. Formula 1

    http://acm.timus.ru/problem.aspx?space=1&num=1519 题意:给一个n×m的棋盘,其中'.'是空白,'*'是障碍,求经过所有点的哈密顿回路的数目.( ...

  7. Python3 函数

    函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 函数能提高应用的模块性,和代码的重复利用率.你已经知道Python提供了许多内建函数,比如print().但你也可以自己创建函数,这 ...

  8. c# 集合

    集合适用于元素个数是动态的情况. 当使用默认的构造函数创建一个空列表后(未指定容量),集合的容量为0:当往集合内添加元素,容量将变为4*2^n(n为0或正整数).当指定集合的大小为size后,容量将变 ...

  9. ionic+angularjs开发hybrid App(环境配置+创建测试项目)

    本文使用的系统是win10 因为后期需要使用nodejs 所以先把node装好 https://nodejs.org/download/ 下载JDK并配置Java运行环境 http://www.ora ...

  10. 神经网络和Deep Learning

    参考资料: 在线免费书籍 http://neuralnetworksanddeeplearning.com/chap1.html Chapter 1 1.  perceptron 感知机 it's a ...