神奇的i++

i++,++i,多简单啊,不需要深入研究吧!!!

我是这样想的。

直到我做了一道Java基础检测题,才发现,哦,原来是这样啊!!!

题是这样的

  1. public class Demo {
  2. public static void main(String args[]) {
  3. int num = 50 ;
  4. num = num ++ * 2 ;
  5. System.out.println(num) ;
  6. }
  7. }
  8. 最终的执行结果是什么?

结果是什么?100?102?101?

正确输出是:100

对了就不必往下看了.

Javap介绍

先来看个有用的指令:javap

javap:

javap是jdk自带的反解析工具,通过反编译生成的汇编代码,我们可以深入的了解java代码的工作机制

javap的用法格式:

javap

classes就是你要反编译的class文件

  1. D:\notepadd++cache>javap
  2. 用法: javap <options> <classes>
  3. 其中, 可能的选项包括:
  4. -help --help -? 输出此用法消息
  5. -version 版本信息
  6. -v -verbose 输出附加信息
  7. -l 输出行号和本地变量表
  8. -public 仅显示公共类和成员
  9. -protected 显示受保护的/公共类和成员
  10. -package 显示程序包/受保护的/公共类
  11. 和成员 (默认)
  12. -p -private 显示所有类和成员
  13. -c 对代码进行反汇编
  14. -s 输出内部类型签名
  15. -sysinfo 显示正在处理的类的
  16. 系统信息 (路径, 大小, 日期, MD5 散列)
  17. -constants 显示最终常量
  18. -classpath <path> 指定查找用户类文件的位置
  19. -cp <path> 指定查找用户类文件的位置
  20. -bootclasspath <path> 覆盖引导类文件的位置

Jvm指令介绍

这是接下来要用到的Jvm指令的含义,推荐一篇JVM指令博客JVM指令介绍博客

//指令含义

bipush : valuebyte值带符号扩展成int值入栈

istore : 将栈顶int类型值保存到局部变量indexbyte中

iinc : 将指定int型变量增加指定值(i++, i--, i+=2)

iload : 从局部变量indexbyte中装载int类型值入栈

iconst_2: 2(int)值入栈

imul : 将栈顶两int类型数相乘,结果入栈。

分析

通过javap来分析下程序的运行机制

把这段代码放到StrTest.java中

  1. public class StrTest {
  2. public static void main(String args[]) {
  3. int num1 = 50 ;
  4. num1 = num1++ * 2 ;
  5. System.out.println(num1) ;
  6. }
  7. }

通过cmd执行javac StrTest.java ->javap -c StrTest.class得到如下反汇编代码

  1. public class StrTest {
  2. public StrTest();
  3. Code:
  4. 0: aload_0
  5. 1: invokespecial #1 // Method java/lang/Object."<init>":()V
  6. 4: return
  7. public static void main(java.lang.String[]);
  8. Code:
  9. 0: bipush 50
  10. 2: istore_1
  11. 3: iload_1
  12. 4: iinc 1, 1
  13. 7: iconst_2
  14. 8: imul
  15. 9: istore_1
  16. 10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
  17. 13: iload_1
  18. 14: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
  19. 17: return
  20. }

把上边的内容添加上注释,瞬间就能明白,为啥结果是100了。

  1. public static void main(java.lang.String[]);
  2. Code:
  3. 0: bipush 50 //把50推入栈顶top
  4. 2: istore_1 //将50保存到第二个局部变量中->num1=50
  5. 3: iload_1 //把局部变量num1的值推入栈顶,此时栈顶值top是50
  6. 4: iinc 1, 1 //将50执行加1->50+1 局部变量num1值是51
  7. 7: iconst_2 //把2推入栈顶
  8. 8: imul //把50和2相乘,并把结果100推入栈顶,此时栈顶值top是100
  9. 9: istore_1 //把100保存到第二个局部变量中->num1=100
  10. 10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
  11. 13: iload_1
  12. 14: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
  13. 17: return

通过Jvm指令解析后,可知程序经过的步骤是这样的:

  1. 把50推入栈顶,栈顶值是50
  2. num1的值是50
  3. num1执行自增->num1=51
  4. 把2推入栈顶,栈顶值是2
  5. 执行50*2并保存到栈顶,栈顶值是100
  6. 把栈顶值赋给num1->num1=100

同理,++i也好理解了,把上边程序的num1++改为++num1

结果102,再分析下执行步骤

  1. public static void main(java.lang.String[]);
  2. Code:
  3. 0: bipush 50 //把50推入栈顶top
  4. 2: istore_1 //将50保存到第二个局部变量中->num1=50
  5. 3: iinc 1, 1 //将50执行加1->50+1 局部变量num1值是51
  6. 6: iload_1 //把局部变量num1的值推入栈顶,此时栈顶值top是51
  7. 7: iconst_2 //把2推入栈顶
  8. 8: imul //把51和2相乘,并把结果102推入栈顶,此时栈顶值top是102
  9. 9: istore_1 //把102保存到第二个局部变量中->num1=102
  10. 10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
  11. 13: iload_1
  12. 14: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
  13. 17: return

通过Jvm指令解析后,可知程序经过的步骤是这样的:

  1. 把50推入栈顶,栈顶值是50
  2. num1的值是50
  3. num1执行自增->num1=51
  4. 把num1的值推入栈顶,栈顶的值是51
  5. 把2推入栈顶,栈顶值是2
  6. 执行51*2并保存到栈顶,栈顶值是102
  7. 把栈顶值赋给num1->num1=102

结束

ok,分析结束,又温习了一遍指令,记录一下

神奇的i++的更多相关文章

  1. BZOJ 1006 【HNOI2008】 神奇的国度

    题目链接:神奇的国度 一篇论文题--神奇的弦图,神奇的MCS-- 感觉我没有什么需要多说的,这里简单介绍一下MCS: 我们给每个点记录一个权值,从后往前依次确定完美消除序列中的点,每次选择权值最大的一 ...

  2. 前端精选文摘:BFC 神奇背后的原理

    BFC 已经是一个耳听熟闻的词语了,网上有许多关于 BFC 的文章,介绍了如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等).虽然我知道如何利用 BFC 解决这些问题, ...

  3. MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)

    前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...

  4. 一行神奇的javascript代码

    写本篇文章的缘由是之前群里@墨尘发了一段js代码,如下: (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~ ...

  5. [翻译svg教程]Path元素 svg中最神奇的元素!

    先看一个实例 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999 ...

  6. php isset( $test ) 的神奇之处。

    很久一段时间没更新博客了,由于近段时间一直在忙 挑战杯 的项目,所以没怎样把一些总结放上来.这次,总结下 php 的一个 函数 : boolean isset($test), 返回值:boolean类 ...

  7. 神奇的CSS3按钮特效

    点击这里查看效果 以下是源代码: <!doctype html> <html> <!-- author: @simurai --> <head> < ...

  8. 吉特仓库管理系统- 斑马打印机 ZPL语言的腐朽和神奇

    上一篇文章说到了.NET中的打印机,在PrintDocument类也暴露一些本质上上的问题,前面也提到过了,虽然使用PrintDcoument打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...

  9. JS开发HTML5游戏《神奇的六边形》(一)

    近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...

  10. 神奇的sort()函数

    今天来谈一谈sort()函数,sort() 方法用于对数组的元素进行排序,用法为arrayObject.sort(sortby):括号中的为可选参数,准确来说应该是一个函数,这个函数用来规定排序方法, ...

随机推荐

  1. bootstrap帮助文档

    概览 深入了解 Bootstrap 底层结构的关键部分,包括我们让 web 开发变得更好.更快.更强壮的最佳实践. HTML5 文档类型 Bootstrap 使用到的某些 HTML 元素和 CSS 属 ...

  2. 3_06_MSSQL课程_Ado.Net_接口、委托、事件、观察者模式

    1.接口——实现接口 2.委托.事件(定义事件.注册事件.触发事件) 3.接口和事件的区别,怎么分情况用? 4.观察者模式作为设计模式的一种,也称发布订阅模式. 应对类型的变化和个数的变化. 中介设计 ...

  3. jsoup教学系列

    http://my.oschina.net/flashsword/blog?catalog=390084

  4. redhat 7.6 ssh 服务配置

    安装ssh yum install openssh 查看端口 netstat -ntpl netstat -ntpl | grep :22 启动和关闭 service sshd restart/sta ...

  5. Centos7 iptables firewalld防火墙与selinux配置

    一.iptables防火墙 1.基本操作 # 查看防火墙状态 service iptables status # 停止防火墙 service iptables stop # 启动防火墙 service ...

  6. 2018 蓝桥杯省赛 B 组模拟赛

    C. 结果填空:U型数字 最近蒜头君喜欢上了U型数字,所谓U型数字,就是这个数字的每一位先严格单调递减,后严格单调递增.比如 212 就是一个U型数字,但是 333, 98, 567, 3131,就是 ...

  7. scrapy 中没有 crawl 命令

    确保两点: 1.把爬虫.py 复制到 spider 文件夹里 如 执行 scrapy crawl demo.py (spiders 中就要有 demo.py 文件) 2.在项目文件夹内执行命令 在 s ...

  8. Melodic 使用URDF创建简单的机器人模型

    本人Linux版本:Ubuntu 18.04LTS ROS版本:Melodic URDF代码 <?xml version="1.0" ?> <robot name ...

  9. redis之string数据类型常用方法总结

    目录 redis 字符串(string)[需要掌握] 特点 语法 redis 字符串(string)[需要掌握] 特点 一个键能存储512MB数据 string类型是二进制安全的,可以存储任何数据,比 ...

  10. 一个Win32程序的进化------转载

    一个Win32程序的进化 转载 weixin_34273046 发布于2017-11-15 10:53:00 阅读数 10 收藏 展开 一.为什么要学Win32     要回答这个问题,我们就要先搞清 ...