神奇的i++
神奇的i++
i++,++i,多简单啊,不需要深入研究吧!!!
我是这样想的。
直到我做了一道Java基础检测题,才发现,哦,原来是这样啊!!!
题是这样的
public class Demo {
public static void main(String args[]) {
int num = 50 ;
num = num ++ * 2 ;
System.out.println(num) ;
}
}
最终的执行结果是什么?
结果是什么?100?102?101?
正确输出是:100
对了就不必往下看了.
Javap介绍
先来看个有用的指令:javap
javap:
javap是jdk自带的反解析工具,通过反编译生成的汇编代码,我们可以深入的了解java代码的工作机制
javap的用法格式:
javap
classes就是你要反编译的class文件
D:\notepadd++cache>javap
用法: javap <options> <classes>
其中, 可能的选项包括:
-help --help -? 输出此用法消息
-version 版本信息
-v -verbose 输出附加信息
-l 输出行号和本地变量表
-public 仅显示公共类和成员
-protected 显示受保护的/公共类和成员
-package 显示程序包/受保护的/公共类
和成员 (默认)
-p -private 显示所有类和成员
-c 对代码进行反汇编
-s 输出内部类型签名
-sysinfo 显示正在处理的类的
系统信息 (路径, 大小, 日期, MD5 散列)
-constants 显示最终常量
-classpath <path> 指定查找用户类文件的位置
-cp <path> 指定查找用户类文件的位置
-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中
public class StrTest {
public static void main(String args[]) {
int num1 = 50 ;
num1 = num1++ * 2 ;
System.out.println(num1) ;
}
}
通过cmd执行javac StrTest.java ->javap -c StrTest.class得到如下反汇编代码
public class StrTest {
public StrTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: bipush 50
2: istore_1
3: iload_1
4: iinc 1, 1
7: iconst_2
8: imul
9: istore_1
10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
13: iload_1
14: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
17: return
}
把上边的内容添加上注释,瞬间就能明白,为啥结果是100了。
public static void main(java.lang.String[]);
Code:
0: bipush 50 //把50推入栈顶top
2: istore_1 //将50保存到第二个局部变量中->num1=50
3: iload_1 //把局部变量num1的值推入栈顶,此时栈顶值top是50
4: iinc 1, 1 //将50执行加1->50+1 局部变量num1值是51
7: iconst_2 //把2推入栈顶
8: imul //把50和2相乘,并把结果100推入栈顶,此时栈顶值top是100
9: istore_1 //把100保存到第二个局部变量中->num1=100
10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
13: iload_1
14: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
17: return
通过Jvm指令解析后,可知程序经过的步骤是这样的:
- 把50推入栈顶,栈顶值是50
- num1的值是50
- num1执行自增->num1=51
- 把2推入栈顶,栈顶值是2
- 执行50*2并保存到栈顶,栈顶值是100
- 把栈顶值赋给num1->num1=100
同理,++i也好理解了,把上边程序的num1++改为++num1
结果102,再分析下执行步骤
public static void main(java.lang.String[]);
Code:
0: bipush 50 //把50推入栈顶top
2: istore_1 //将50保存到第二个局部变量中->num1=50
3: iinc 1, 1 //将50执行加1->50+1 局部变量num1值是51
6: iload_1 //把局部变量num1的值推入栈顶,此时栈顶值top是51
7: iconst_2 //把2推入栈顶
8: imul //把51和2相乘,并把结果102推入栈顶,此时栈顶值top是102
9: istore_1 //把102保存到第二个局部变量中->num1=102
10: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
13: iload_1
14: invokevirtual #3 // Method java/io/PrintStream.println:(I)V
17: return
通过Jvm指令解析后,可知程序经过的步骤是这样的:
- 把50推入栈顶,栈顶值是50
- num1的值是50
- num1执行自增->num1=51
- 把num1的值推入栈顶,栈顶的值是51
- 把2推入栈顶,栈顶值是2
- 执行51*2并保存到栈顶,栈顶值是102
- 把栈顶值赋给num1->num1=102
结束
ok,分析结束,又温习了一遍指令,记录一下
神奇的i++的更多相关文章
- BZOJ 1006 【HNOI2008】 神奇的国度
题目链接:神奇的国度 一篇论文题--神奇的弦图,神奇的MCS-- 感觉我没有什么需要多说的,这里简单介绍一下MCS: 我们给每个点记录一个权值,从后往前依次确定完美消除序列中的点,每次选择权值最大的一 ...
- 前端精选文摘:BFC 神奇背后的原理
BFC 已经是一个耳听熟闻的词语了,网上有许多关于 BFC 的文章,介绍了如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等).虽然我知道如何利用 BFC 解决这些问题, ...
- MVC系列——MVC源码学习:打造自己的MVC框架(四:了解神奇的视图引擎)
前言:通过之前的三篇介绍,我们基本上完成了从请求发出到路由匹配.再到控制器的激活,再到Action的执行这些个过程.今天还是趁热打铁,将我们的View也来完善下,也让整个系列相对完整,博主不希望烂尾. ...
- 一行神奇的javascript代码
写本篇文章的缘由是之前群里@墨尘发了一段js代码,如下: (!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~ ...
- [翻译svg教程]Path元素 svg中最神奇的元素!
先看一个实例 <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999 ...
- php isset( $test ) 的神奇之处。
很久一段时间没更新博客了,由于近段时间一直在忙 挑战杯 的项目,所以没怎样把一些总结放上来.这次,总结下 php 的一个 函数 : boolean isset($test), 返回值:boolean类 ...
- 神奇的CSS3按钮特效
点击这里查看效果 以下是源代码: <!doctype html> <html> <!-- author: @simurai --> <head> < ...
- 吉特仓库管理系统- 斑马打印机 ZPL语言的腐朽和神奇
上一篇文章说到了.NET中的打印机,在PrintDocument类也暴露一些本质上上的问题,前面也提到过了,虽然使用PrintDcoument打印很方便.对应条码打印机比如斑马等切刀指令,不依赖打印机 ...
- JS开发HTML5游戏《神奇的六边形》(一)
近期出现一款魔性的消除类HTML5游戏<神奇的六边形>,今天我们一起来看看如何通过开源免费的青瓷引擎(www.zuoyouxi.com)来实现这款游戏. (点击图片可进入游戏体验) 因内容 ...
- 神奇的sort()函数
今天来谈一谈sort()函数,sort() 方法用于对数组的元素进行排序,用法为arrayObject.sort(sortby):括号中的为可选参数,准确来说应该是一个函数,这个函数用来规定排序方法, ...
随机推荐
- scp 常用命令总结
1, 上传本地文件到服务器:scp /path/local_filename username@servername:/path 例如:例如scp /var/www/test.php codingl ...
- [蓝桥杯2015决赛]穿越雷区(BFS求最短路)
题目描述 X星的坦克战车很奇怪,它必须交替地穿越正能量辐射区和负能量辐射区才能保持正常运转,否则将报废.某坦克需要从A区到B区去(A,B区本身是安全区,没有正能量或负能量特征),怎样走才能路径最短?已 ...
- 如何编写README.md
一.标题写法 1.在文本下方加上 =,文本变为大标题 2.在文本下方加上-,文本变为中标题 3.单独向输入 = ,则需要空一行 标题的另一种写法: # 一级标题 ## 二级标题 ### 三级标题 ## ...
- Python环境搭建-4 pip的安装和使用
pip的安装和使用 我们都知道python有很多的第三方库或者说是模块.这些库针对不同的应用,发挥不同的作用.我们在实际的项目中肯定会用到这些模块.那如何将这些模块导入到自己的项目中呢? Python ...
- LeetCode困难题(一)
题目一: 给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表. k 是一个正整数,它的值小于或等于链表的长度. 如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序. 示例 ...
- Codeforces Round #594 (Div. 2) - C. Ivan the Fool and the Probability Theory(思维)
题意:给n*m的网格涂黑白两种颜色,保证每个格子上下左右的四个格子中最多只有一个格子与自己颜色相同,问有多少种涂法?结果$mod1000000007$ 思路:先只考虑一行有多少种涂法 $dp[i][0 ...
- 如何往gitlab/github上游贡献代码
Git 是一个开源的分布式版本控制系统,它能够记录每一次改动. 一些概念 仓库:git 中以仓库为单位:每个项目对应一个仓库,如 /eayuntest/Rally./eayuntest/stack 是 ...
- android悬浮按钮(Floating action button)的两种实现方法
原文: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1028/1857.html 最近android中有很多新的设计规范被引入 ...
- windows下代码规范检测工具sonarqube安装与使用,含与maven的结合
一.首先下载sonarqube 地址 : https://www.sonarqube.org/downloads/ (最新版本支持java11+,博主下载支持java8的版本7.7), 下载S ...
- Java连载78-深入自动拆装箱、Date类和SimpleDateFormat格式化
一.深入自动拆装箱 1.直接举例: public class D78_AutomaticUnpackingAndPacking{ public static void main(String[] ar ...