一篇文章带你从java字节码层理解i++和++i

目录
  • 程序目的
  • 关键指令
  • i++示例源码
  • 使用jclasslib查看i++字节码
  • ++i示例源码
  • 参考
  • 总结

程序目的

从java字节码层理解,为何i = i++后,结果是+1之前的数值。而i=++i后,结果是+1之后的值。

关键指令

iload_<n>:从局部变量表获取值,并压入操作数栈。

istore_<n>:出栈,然后存储到局部变量表。

i++示例源码

public class TestIPulsPlus {
	public static void main(String[] args) {
		int i = 8;
		i = i++;
//        i = ++i;
		System.out.println(i);
	}
}

i++执行结果:

8

使用jclasslib查看i++字节码

找到main方法的Code区:

图:i=i++字节码

字节码解读

0 bipush 8
把数值8压入操作数栈,压栈前转为int类型。
2 istore_1
8出栈,存到编号为1的局部变量表。

图:编号为1的局部变量为1

以上两行指令,完成了int i = 8;这行代码。

3 iload_1
从局部变量表,获取int值8。然后压到操作数栈。
4 iinc 1 by 1
把局部变量表中的i,进行+1操作。此时栈里面数值是8,局部变量表中i为9。
7 istore_1
8出栈,存到编号为1的局部变量表。也就是赋值给i变量。局部变量表的i值从9变为8。

接下来,解读i=++i的字节码

图:i=++i;字节码

++i示例源码

public class TestIPulsPlus {
	public static void main(String[] args) {
		int i = 8;
//		i = i++;
        i = ++i;
		System.out.println(i);
	}
}

执行结果为:

9

i=++i字节码解读

0 bipush 8
把数值8压入操作数栈,压栈前转为int类型。
2 istore_1
8出栈,存到编号为1的局部变量表。

图:编号为1的局部变量为1

以上两行指令,完成了int i = 8;这行代码。

3 iinc 1 by 1
把局部变量表中的i,进行+1操作。此时,局部变量表中i为9。
6 iload_1
从局部变量表,获取int值9。然后压到操作数栈。
7 istore_1
9出栈,存到编号为1的局部变量表。也就是赋值给i变量。

参考

Chapter 6. The Java Virtual Machine Instruction Set

总结

i=i++i=++i,第3、4行位置是相反的。

i++是先执行iload_1,再执行iinc 1 by 1。

iload_1:从局部变量表,获取int值8。然后压到操作数栈。

iinc 1 by 1 :把局部变量表中的i,进行+1操作。此时栈里面数值是8,局部变量表中i为9。

istore_1时,获取的是栈中的8,所以最后结果为8。

++i,是先执行iinc 1 by 1,再执行iload_1

iinc 1 by 1 : 把局部变量表中的i,进行+1操作。此时,局部变量表中i为9。

iload_1:从局部变量表,获取int值9。然后压到操作数栈。

istore_1时,获取的是栈中的9,所以最后结果为9。

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • 详解java面试题中的i++和++i

    代码如下所示: public class TestPlusPlus{ public static void main(String[] args){ int k = addAfterReturn(10); System.out.println(k); //输出 10 int k1 = addbeforeReturn(10); System.out.println(k1); //输出11 } public static int addbeforeReturn(int i){ return ++i;

  • java中i = i++和i =++i的深入讲解

    public class Count { public static void main(String[] args) { int i = 0; i = i++ ; System.out.println(i); } } 上面代码输出的i为0,如果是把i = i++换成i=++i,又会输出1,这是由于i++是先赋值,再计算导致,但是为什么先赋值呢? public static void main(String[] args) { int i = 0; i++ ; } public static v

  • 深入理解java中i++和++i的区别

    今天简单谈谈关于java的一个误区,相信很多刚开始学习java的朋友都会遇到这个问题,虽然问题很简单,但是经常容易搞混,说说java的i++和++i的区别. 先看一下代码: <span style="font-size:18px;">public class test { public static void main(String[] args) { int i = 0; for (int j = 0; j < 10; j++) { i=i++; } System.

  • Java中i++与++i的区别和使用

    书上对 i ++  和 ++ i 的解释如下: int i = 3,a = 0 : i ++ : 先赋值再运算:例如:a = i ++; 先赋值 a = i ,再运算 i = i + 1 :所以输出结果为 a ==3; ++ i : 先运算再赋值:例如:a = i ++; 先运算 i = i + 1 ,再 赋值 a = i :所以输出结果为 a ==4; 懂了吗?我想大部分人会跟我一样 一脸懵逼,明明都 + 1 了,咋上面输出结果是 3 下面就是 4 呢?哈哈~不要着急,接下来我将分享一下我对它

  • java中的i++和++i的区别详解

    java中的前加加++和后加加++,有很多人搞的很晕,不太明白!今天我举几个例子说明下前++和后++的区别! 其实大家只要记住一句话就可以了,前++是先自加再使用而后++是先使用再自加! 前++和后++总结:其实大家只要记住一句话就可以了,前++是先自加再使用而后++是先使用再自加! 请大家看下面的例子就明白了! public class Test { public static void main(String[] args) { //测试,前加加和后加加 //前++和后++总结:其实大家只要

  • 一篇文章带你从java字节码层理解i++和++i

    目录 程序目的 关键指令 i++示例源码 使用jclasslib查看i++字节码 ++i示例源码 参考 总结 程序目的 从java字节码层理解,为何i = i++后,结果是+1之前的数值.而i=++i后,结果是+1之后的值. 关键指令 iload_<n>:从局部变量表获取值,并压入操作数栈. istore_<n>:出栈,然后存储到局部变量表. i++示例源码 public class TestIPulsPlus { public static void main(String[]

  • 一篇文章带你了解Java Spring基础与IOC

    目录 About Spring About IOC Hello Spring Hello.java Beans.xml Test.java IOC创建对象的几种方式 Spring import settings Dependency Injection 1.构造器注入 2.set注入 3.拓展注入 P-namespcae&C-namespace Bean scopes singleton prototype Bean的自动装配 byName autowire byType autowire 小结

  • 一篇文章带你了解Java中ThreadPool线程池

    目录 ThreadPool 线程池的优势 线程池的特点 1 线程池的方法 (1) newFixedThreadPool (2) newSingleThreadExecutor (3) newScheduledThreadPool (4) newCachedThreadPool 2 线程池底层原理 3 线程池策略及分析 拒绝策略 如何设置maximumPoolSize大小 ThreadPool 线程池的优势 线程池做的工作主要是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些

  • 一篇文章带你复习java知识点

    JDK JRE JVM JDK: Java标准开发包,它提供了编译.运⾏Java程序所需的各种⼯具和资源,包括Java编译器.Java运⾏时环境,以及常⽤的Java类库等. JRE: Java运⾏环境,⽤于解释执⾏Java的字节码⽂件. JVM Java虚拟机,是JRE的⼀部分.负责解释执⾏字节码⽂件,是可运⾏java字节码⽂件的虚拟计算机 区别联系:(问答题会考可能) JDK包含JRE,JDK 和 JRE 中都包含 JVM.JDK出了包含jre还包含⼀些常⽤开发⼯具和基础类库 JDK ⽤于开发

  • 一篇文章带你入门Java基本概念

    目录 Java基本概念 一.JRE(Java运行时环境) 二.JDK(Java开发工具) 三.Java源代码文件(.class) 四.Java字节码文件(.java) 五.Java虚拟机(JVM) 六.跨平台运行 七.JDK与JRE.JVM的关系? 八.几个结论 总结 Java基本概念 JDK包含了不少Java开发相关命令.如,javac.java.javap.javaw.javadoc.虽然现在的Java开发都使用IDE完成,基本上不会直接使用这些命令.但是理解这些命令的用法,可以让我们更加扎

  • 一篇文章带你了解Java 中序列化与反序列化

    目录 一. 序列化和反序列化概念 二. 序列化和反序列化的必要性 三. 序列化和反序列化的实现 1. JDK类库提供的序列化API 2. 实现序列化的要求 3. 实现Java对象序列化与反序列化的方法 4. JDK类库中序列化的步骤 5. JDK类库中反序列化的步骤 四.序列化的必要条件 五.序列化高级,使用情境分析 1. 序列化ID问题 特性使用案例 2. 静态变量序列化 3. 父类的序列化与 Transient 关键字 4. 对敏感字段加密 5. 序列化存储规则 总结 一. 序列化和反序列化

  • 一篇文章带你入门Java Script

    目录 概述 特点 和Java的区别 弱类型语言 强类型语言 书写位置 数组 函数 JS中的自定义对象(扩展内容) Object形式的自定义对象 JS中的事件 常用的事件: 动态注册基本步骤: DOM模型 总结 概述 JavaScript是目前web开发中不可缺少的脚本语言,js不需要编译即可运行,运行在客户端,需要通过浏览器来解析执行JavaScript代码. JS组成部分: 组成部分 作用 ECMA Script 构成了JS核心的语法基础 BOM Browser Object Model 浏览

  • 一篇文章带你了解JAVA面对对象应用

    目录 常用API String类 关于String为啥不可改变 StringBuilder类 String.StringBuffer 和 StringBuilder 的区别: ArrayList 1.1ArrayList类概述 1.2ArrayList类常用方法 学生管理系统 总结 常用API API理解 什么是API API (Application Programming Interface) :应用程序编程接口 java中的API 指的就是 JDK 中提供的各种功能的 Java类,这些类将

  • 一篇文章带你入门java面向对象

    目录 一.继承 示例: 二.重载 三.接口 1.接口与类相似点: 2.接口与类的区别: 3.语法 四.枚举 1.定义 2.迭代枚举元素 3.在 switch 中使用枚举类 总结 一.继承 继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为 本章就以人.学生.老师作为例子.学生和老师都继承人这个对象,都有人的特征和行为,人就是父类,老师和学生就是子类 示例: 人类: package com.zhouzy.base.t7;

  • 一篇文章带你了解Java之关键字和保留字

    目录 引言 概念 关键字分类 1.访问控制 2.类.方法和变量修饰符 3.程序控制语句 4.错误处理 5包相关 6.基本类型 7.变量引用 8.保留关键字 9.其他(个人认为不是关键字.也不是保留字,但是,如果尝试将它们用作Java中的标识符,仍然会生成编译时错误.) 总结 引言 ♀ 小AD:小明哥,前几天边学Java边学连招,我感觉上分如喝水,我这连招很熟练哦. ♂ 明世隐:跟明哥混,舒服吧! ♀ 小AD:舒服啊,回头请你喝奶茶! ♂ 明世隐:乖,懂事! ♀ 小AD:那今天整点啥? ♂ 明世隐

随机推荐