图解 i++ 和 ++i 的区别,看了必懂...

简介: 图解 i++ 和 ++i 的区别,看了必懂...

先看一段代码:

int i = 0;
int a = i++;
sout("a的值是:"+i);
sout("i的值是:"+i);• 1
• 2
• 3


最终的编译之后的核心字节码如下

L0
 BITPUSH 0  //将常量0压入操作栈
 ISTORE_1  //将当前栈顶元素,弹出并保存到局部变量表的slot_1中
L1
 ILOAD_1   //从局部变量表的第一个slot槽中,取出该值,压入操作栈顶
 IINC 0,1    //直接将slot槽中的值自增(+1)操作,注意此时是与当前栈无关的
 ISTORE_2   //将当前栈顶元素,弹出并保存到局部变量表的slot_2中
L2
 ILOAD_2    //从局部变量表的第二个slot槽中,取出该值,压入操作栈顶
  IRETURN  //返回栈顶元素


这里有两个注意点:

  • IINC 的自增操作,并未影响当前的栈顶元素,并且 slot_1 中的元素自增完成后,已经由0变成了1
  • ISTORE_2 弹出的栈顶元素值依旧是0,并未改变


最终的输出的结果为:

a的值是: 0
i的值是: 1;


我这里画了一个图来帮助大家理解

image.png

image.pngimage.png

image.png

image.png

image.png


再来看看++i

int i = 0;
int a = ++i;
sout("a的值是:"+i);
sout("i的值是:"+i);


对于++i 来说,对应的字节码如下,先自增再入栈,那么结果就很清晰了

最终的核心编译之后的字节码如下


L0
 BITPUSH 0  //将常量0压入操作栈
 ISTORE_1  //将当前栈顶元素,弹出并保存到局部变量表的slot_1中
L1
 IINC 0,1    //直接将slot槽中的值自增(+1)操作
 ILOAD_1   //从局部变量表的第一个slot槽中,取出该值(该值此时已经自增过了),压入操作栈顶
 ISTORE_2   //将当前栈顶元素,弹出并保存到局部变量表的slot_2中
L3
 ILOAD_2    //从局部变量表的第二个slot槽中,取出该值,压入操作栈顶
 IRETURN  //返回栈顶元素


最终的输出的结果为:

a的值是: 1
i的值是: 1;


总结

i++ 和 ++i 在理论上的区别是 :

  • i++:是先把i拿出来使用,然后再+1;
  • ++i :是先把i+1,然后再拿出来使用;
相关文章
|
XML 安全 前端开发
Spring Security—Spring MVC 整合
Spring Security—Spring MVC 整合
519 1
|
安全 前端开发 Java
Spring Security系列教程25--解决Spring Security环境中的跨域问题
前言 上一章节中,一一哥 给各位讲解了同源策略和跨域问题,以及跨域问题的解决方案,在本篇文章中,我会带大家进行代码实现,看看在Spring Security环境中如何解决跨域问题。 一. 启用Spring Security 的CORS支持 1. 创建web接口 我先在SpringBoot环境中,创建一个端口号为8080的web项目,注意这个web项目没有引入Spring Security的依赖包。然后在其中创建一个IndexController,定义两个测试接口以便被ajax进行跨域访问。 @RestController public class IndexController {
1636 1
|
SQL 算法 Java
Mybatis-plus超详细讲解(2022)
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。 我们的愿景是成为 MyBatis 最好的搭档,就像 魂斗罗 中的 1P、2P,基友搭配,效率翻倍。
4268 1
|
8月前
|
缓存 监控 Java
java动态代理
本文介绍了Java中的动态代理及其优势,通过增强原有方法或拦截调用实现无侵入式代码扩展,如添加日志、缓存等。文章先讲解了静态代理的基本概念和实现方式,随后引出动态代理解决静态代理在多方法、多类场景下的局限性。通过JDK提供的InvocationHandler接口和Proxy类,展示了如何动态生成代理对象。最后,文章还探讨了代理Hook技术,包括寻找Hook点、选择代理方式以及替换原始对象的具体步骤。
242 0
|
9月前
|
SQL Java 关系型数据库
MyBatis篇-分页
本文介绍了多种分页方式,包括自带rowbound内存分页、第三方插件pagehelper(通过修改SQL实现分页)、SQL分页(依赖limit或rownum等关键字)、数组分页(先查询全部数据再用subList分页)、拦截器分页(自定义拦截器为SQL添加分页语句)。最后总结了逻辑分页(内存分页,适合小数据量)和物理分页(直接在数据库层面分页,适合大数据量)的优缺点,强调物理分页优先于逻辑分页。
|
数据可视化 API 索引
ES常见Index API操作最佳实践!
【10月更文挑战第21天】
681 1
ES常见Index API操作最佳实践!
|
前端开发 Java 编译器
classpath中存在多个jar存在同限定名的class classloader会如何加载
总之,合理组织类路径和使用现代化的构建工具,可有效避免类加载冲突,保证应用的稳定运行。
493 8
|
JSON 安全 Java
Spring Security 6.x 微信公众平台OAuth2授权实战
上一篇介绍了OAuth2协议的基本原理,以及Spring Security框架中自带的OAuth2客户端GitHub的实现细节,本篇以微信公众号网页授权登录为目的,介绍如何在原框架基础上定制开发OAuth2客户端。
798 4
Spring Security 6.x 微信公众平台OAuth2授权实战
|
缓存 NoSQL 前端开发
《优化接口设计的思路》系列:第六篇—接口防抖(防重复提交)的一些方式
本文探讨了后端开发中的接口防抖策略,作者是一名有六年经验的Java开发者,分享了如何防止重复提交导致的问题。防抖主要用于避免用户误操作或网络波动引起的多次请求,作者提出理想防抖机制应具备正确性、响应速度、易集成和用户反馈。文章详细分析了哪些接口需要防抖(如用户输入、按钮点击、滚动加载)以及如何识别重复接口,提出了使用共享缓存和分布式锁两种实现方式,并展示了基于Redis的Java代码示例。作者通过注解实现请求锁,并提供了测试截图证明防抖效果。然而,实现完全幂等性还需要业务层面的补充措施。
1146 8
|
存储 安全 JavaScript
SpringBoot中如何使用Cookies
本文介绍了如何在Spring Boot中操作HTTP Cookie。内容包括:使用@CookieValue注解读取Cookie,通过HttpServletResponse设置Cookie,读取所有Cookie,设置Cookie过期时间,理解HTTPS与Cookie安全,使用HttpOnly Cookie防止XSS攻击,以及如何删除Cookie。示例代码展示了各种操作的方法。
416 0