java中i = i++问题
今天偶然呗问到了一个java中自增运算符的问题,涉及到了堆栈,觉得挺有趣的把它记录下来。
int i=0;
i=i++;
结果i是多少?
这是一个经常被提及的问题,答案一直五花八门。
具体测试一下以说明问题:
代码1:
- public class Test{
- public static void main(String[] args){
- int i=0;
- i=i++;
- System.out.println(i);
- }
- }
结果i依然是0.分析其反编译后的代码:
- public static void main(java.lang.String[]);
- Code:
- 0: iconst_0 //0放到栈顶
- 1: istore_1 //把栈顶的值保存到局部变量1,也就是i中
- 2: iload_1 //把i的值放到栈顶,也就是说此时栈顶的值是0
- 3: iinc 1, 1 //注意这个指令,把局部变量1,也就是i,增加1,这个指令不会导致栈的变化,也就是说局部变量1,即i此时为1了。
- 6: istore_1 //把栈顶的值(0)保存到局部变量1,也就是让i为0了,所以最后i为0
- 7: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
- 10: iload_1
- 11: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
- 14: return
值得注意到是i被修改了两次,第一次是i++;i变为1,最后一次是i=0;所以结果i是0
代码2:
- public class Test2{
- public static void main(String[] args){
- int i=0;
- int j=0;
- j=i++;
- System.out.println(i);
- System.out.println(j);
- }
- }
这个结果肯定都知道,i是1,j是0.同样看反编译之后的代码:
- public static void main(java.lang.String[]);
- Code:
- 0: iconst_0
- 1: istore_1 //i=0
- 2: iconst_0
- 3: istore_2 //j=0
- 4: iload_1 //把i的值放到栈顶,也就是说此时栈顶的值是0
- 5: iinc 1, 1 //局部变量1加1,也就是让i++了,此时i已经是1了,上面说过,此指令不会导致栈变化
- 8: istore_2 //把栈顶的值(注意是0)存入局部变量2,也就是j中,所以j=0
- 9: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
- 12: iload_1
- 13: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
- 16: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
- 19: iload_2
- 20: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
- 23: return
很明显可以看出,java是先把i的值取出来放到栈顶,我们可以认为是引入了第三个变量int k=i;然后i++,这时候i为1了,然后让j=k;也就是0.结论,i的++运算是在对j这个变量的赋值之前完成的。
代码3:
- public class Test3{
- public static void main(String[] args){
- int i=0;
- int j=0;
- j=++i;
- System.out.println(i);
- System.out.println(j);
- }
- }
结果大家也都知道,i=1,j=1
看操作过程:
- public static void main(java.lang.String[]);
- Code:
- 0: iconst_0
- 1: istore_1 //i=0
- 2: iconst_0
- 3: istore_2 //j=0
- 4: iinc 1, 1 //局部变量i加1,这时候i变成1了 。
- 7: iload_1 //把i的值放到栈顶,栈顶的值是1
- 8: istore_2 //j=1
- 9: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
- 12: iload_1
- 13: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
- 16: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
- 19: iload_2
- 20: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
- 23: return
对比代码2和代码3,关键的差别就是iload_1 个iinc这两条指令的位置变了。
java中i = i++问题的更多相关文章
- java中的锁
java中有哪些锁 这个问题在我看了一遍<java并发编程>后尽然无法回答,说明自己对于锁的概念了解的不够.于是再次翻看了一下书里的内容,突然有点打开脑门的感觉.看来确实是要学习的最好方式 ...
- java中的字符串相关知识整理
字符串为什么这么重要 写了多年java的开发应该对String不陌生,但是我却越发觉得它陌生.每学一门编程语言就会与字符串这个关键词打不少交道.看来它真的很重要. 字符串就是一系列的字符组合的串,如果 ...
- Java中的Socket的用法
Java中的Socket的用法 Java中的Socket分为普通的Socket和NioSocket. 普通Socket的用法 Java中的 ...
- java中Action层、Service层和Dao层的功能区分
Action/Service/DAO简介: Action是管理业务(Service)调度和管理跳转的. Service是管理具体的功能的. Action只负责管理,而Service负责实施. DAO只 ...
- Java中常用集合操作
一.Map 名值对存储的. 常用派生类HashMap类 添加: put(key,value)往集合里添加数据 删除: clear()删除所有 remove(key)清除单个,根据k来找 获取: siz ...
- java中的移位运算符:<<,>>,>>>总结
java中有三种移位运算符 << : 左移运算符,num << 1,相当于num乘以2 >> : 右移运算符,num >& ...
- 关于Java中进程和线程的详解
一.进程:是程序的一次动态执行,它对应着从代码加载,执行至执行完毕的一个完整的过程,是一个动态的实体,它有自己的生命 周期.它因创建而产生,因调度而运行,因等待资源或事件而被处于等待状态,因完成任务而 ...
- Java中的进程和线程
Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是 ...
- Java中的进程与线程(总结篇)
详细文档: Java中的进程与线程.rar 474KB 1/7/2017 6:21:15 PM 概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进 ...
- 初探java中this的用法
一般this在各类语言中都表示“调用当前函数的对象”,java中也存在这种用法: public class Leaf { int i = 0; Leaf increment(){ i++; retur ...
随机推荐
- Intel GPA 抓取3d模型
原文链接在这里 http://dev.cra0kalo.com/?p=213 背景信息 Intel的GPA本身是一款图形分析软件,并没有设计从3D程序里抓取模型资源的功能,但这里作者是通过hook G ...
- 将Mysql的一张表导出至Excel格式文件
将Mysql的一张表导出至Excel格式文件 导出语句 进入mysql数据库,输入如下sql语句: select id, name, age from tablename into outfile ' ...
- pyhon-爬虫实战抓取豆瓣top250到mysql
采集地址https://movie.douban.com/top250 一.创建mysql数据库 CREATE TABLE `t_doubantop` ( `id` int(11) unsigned ...
- Spring ContextLoaderListener
ContextLoaderListener的作用就是启动Web容器时,自动装配ApplicationContext的配置信息.因为它实现了ServletContextListener这个接口,在web ...
- MySQL 字段全部转换成小写
原因: 因为框架某些字段大写有时候不被正确识别,所以字段都修改成小写; 特别说明:因为这里只有表,没有视图,存储过程等等其它所以我可以直接这么写; 步骤: 1.导出结构语句 2. 执行C# 脚本,替换 ...
- How to push master to QA branch in GIT
1. git branch -d QA2. git branch QA master3. git checkout QA4. git push origin QA(if push error, ...
- 解决maven项目中,缺少 maven dependencies
因为项目需要将普通项目转换为maven项目,在右键 ’项目‘configure 后,添加maven后,发现缺少 maven dependencies,于是从网上找了一些处理措施,大体上是在.class ...
- div的隐藏占用空间位置关系
display:none和visibility:hidden都是把网页上某个元素隐藏起来的功能,但两者有所区别,经过亲自实验,我发现使用 visibility:hidden属性会使对象不可见,但该对象 ...
- 廖雪峰JavaScript练习题3
请尝试写一个验证Email地址的正则表达式.版本一应该可以验证出类似的Email: 正则表达式: <!DOCTYPE html> <html> <head> < ...
- 爬虫之lxml - etree - xpath的使用
# 解析原理: # - 获取页面源码数据 # - 实例化一个etree对象,并且将页面源码数据加载到该对象中 # - 调用该对象的xpath方法进行指定标签定位 # - xpath函数必须结合着xpa ...