JAVA的i++, i+=1, i=i+1有区别吗?
看一些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有区别吗?的更多相关文章
- Java中集合List,Map和Set的区别
Java中集合List,Map和Set的区别 1.List和Set的父接口是Collection,而Map不是 2.List中的元素是有序的,可以重复的 3.Map是Key-Value映射关系,且Ke ...
- Java中的“==操作符”和equals方法有什么区别
Java中的"=="和equals方法究竟有什么区别? 1.==操作符 "=="操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的 ...
- 列举两种不同类型的Java标识注释,并解释它们之间的区别。
列举两种不同类型的Java标识注释,并解释它们之间的区别.
- java多线程之yield,join,wait,sleep的区别
Java多线程之yield,join,wait,sleep的区别 Java多线程中,经常会遇到yield,join,wait和sleep方法.容易混淆他们的功能及作用.自己仔细研究了下,他们主要的区别 ...
- JAVA基础2---深度解析A++和++A的区别
我们都知道JAVA中A++和++A在用法上的区别,都是自增,A++是先取值再自增,++A是先自增再取值,那么为什么会是这样的呢? 1.关于A++和++A的区别,下面的来看个例子: public cla ...
- Java Web开发和Python Web开发之间的区别
今天的文章讨论了Java Web开发和Python Web开发之间的区别.我不鼓励我们在这里从Java Web迁移到Python Web开发.我只是想谈谈我的感受.它不一定适合所有情况,仅供我们参考. ...
- 杂项-Java:jar 包与 war 包介绍与区别
ylbtech-杂项-Java:jar 包与 war 包介绍与区别 1.返回顶部 1. 做Java开发,jar包和war包接触的挺多的,有必要对它们做一个深入的了解,特总结整理如下: 1.jar包的介 ...
- “全栈2019”Java第一百一十章:局部内部类与匿名内部类区别详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- [转]Java五个最常用的集合类之间的区别和联系
Map<String, ?>只能是只读模式,不能增加,因为增加的时候不知道该写入什么类型的值:Map<String, Object>可以读和写,只要是所有Object类的子类都 ...
- java中,return和return null有什么区别吗?
java中,return和return null有什么区别吗? 最大的区别:return;方法的返回值必须是void!return null;方法的返回值必须不是 原始数据类型(封装类除过)和void ...
随机推荐
- 多个不同的app应用间应该如何进行消息推送呢?
现在很多公司做app应用都会用到推送,推送这个不多说了,怎么做网上一堆,用的比较多的还数极光推送(Jpush)以及百度推送,目前我们使用Jpush,文档方面质量是差了点..这个先不吐槽,主要现在的ap ...
- 将对象转化成json字符串
public static String getObjectString(Object object){ String ObjectString = null; try { ObjectMapper ...
- IIS7注册本机模块
问题描述:打开mp4文件要映射给mod_h264_streaming.dll(http://h264.code-shop.com/trac/wiki/Mod-H264-Streaming-Intern ...
- LeetCode "448. Find All Numbers Disappeared in an Array"
My first reaction is to have an unlimited length of bit-array, to mark existence. But if no extra me ...
- The week in .NET - 1/12/2015
On.NET Last week, we had Mads Torgersen on the show to talk about language design in general, and C# ...
- Ceph RGW 和 niginx 配置要点
cat /etc/nginx/sites-enabled/rgw.conf server { listen 80 default; #server_name .com .com.cn .net .cn ...
- Android异步消息处理机制完全解析,带你从源码的角度彻底理解(转)
开始进入正题,我们都知道,Android UI是线程不安全的,如果在子线程中尝试进行UI操作,程序就有可能会崩溃.相信大家在日常的工作当中都会经常遇到这个问题,解决的方案应该也是早已烂熟于心,即创建一 ...
- iOS地图 -- 地理编码和反地理编码
地理编码和反地理编码 用到的类和方法 CLGeocoder --> 地理编码管理器 - (void)geocodeAddressString:(NSString *)addressString ...
- 面向对象(Object-Oriented)
面向对象 面向对象,即我们以对象为核心去实现我们的目的,对象顾名思义:万物皆对象,一个人,一条狗... 当我们通过对象处理一些事情时,会让我们的代码清晰明了,内部高聚合,对外低耦合,即封装的思想 相比 ...
- Zabbix监控mysql主从复制状态
原理 mysql slave show slave status\G 在输出信息中查看I/O线程和SQL线程的状态值(YES为正常,NO为错误) Slave_IO_Running: Yes Slave ...