Java中的自增问题(i=i++)
也许我这是在较真, 但是我们确实有时候就不小心就错写为这种情况了。
看如下代码:
public class Test{
public static void main(String[] args){
int a = 3;
int b = 5;
a = a++;
b = ++b;
}
}
这时候, 如果输出 a 和 b ,那么 他们的值是什么? 答案是 a = 3; b = 6;
如果你感到迷惑, 那么继续往下看, 如果你知道其中的原理,那么就不用看了。
我们利用 jdk 自带的两个命令(javac,javap)来看看 JVM 虚拟机到底在底层做了些什么。
建立一个文件 Test.java 并把上面的代码写入其中, 然后里用 javac 命令编译
wuqinglong@debian:~$ javac -g:vars Test.java
然后利用 javap 命令查看 JVM 编译之后的虚拟机指令。
wuqinglong@debian:~$ javap -verbose Test
输出如下内容
Classfile /home/wuqinglong/Test.class
Last modified 2016-3-16; size 326 bytes
MD5 checksum 2e2f3ec62c26d0e1e53bb121e83b9032
public class Test
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#17 // java/lang/Object."<init>":()V
#2 = Class #18 // Test
#3 = Class #19 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LocalVariableTable
#8 = Utf8 this
#9 = Utf8 LTest;
#10 = Utf8 main
#11 = Utf8 ([Ljava/lang/String;)V
#12 = Utf8 args
#13 = Utf8 [Ljava/lang/String;
#14 = Utf8 a
#15 = Utf8 I
#16 = Utf8 b
#17 = NameAndType #4:#5 // "<init>":()V
#18 = Utf8 Test
#19 = Utf8 java/lang/Object
{
public Test();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LTest;
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=1, locals=3, args_size=1
0: iconst_3 // 将int类型的3送到栈顶
1: istore_1 // 将栈顶的int类型的值存储到slot为1的int类型的本地变量中,slot编号对应的变量名在后三行。
2: iconst_5 // 将int类型的5送到栈顶
3: istore_2 // 将栈顶的int类型的值存储到slot为2的int类型的本地变量中
4: iload_1 // 将slot为1的int类型的本地变量加载到栈顶
5: iinc 1, 1 // 将slot为1的本地int类型的变量的值加1
8: istore_1 // 将栈顶的int类型的值存储到slot为1的本地变量中
9: iinc 2, 1 // 将slot为2的本地intbeijing的变量的值加1
12: iload_2 // 将slot为2的int类型的本地变量加载到栈顶
13: istore_2 // 将栈顶的int类型的值存储到slot为2的int类型的本地变量中
14: return // 结束
LocalVariableTable: // 变量对应的slot编号如下
Start Length Slot Name Signature
0 15 0 args [Ljava/lang/String;
2 13 1 a I
4 11 2 b I
}
如果有点汇编知识的话,看上面的代码会比较好理解点, 如果没有学过汇编指令的话, 就看注释。
其中最主要的区别是:
对于 a = a++; JVM 进行的操作是:
1. 将本地变量的值加载到栈顶 (注意: 这时候这个值是没有经过自增操作的)
2. 对本地变量的值进行自增(对栈顶对象没有影响)
3. 把栈顶变量的值存储到本地变量中(重新对本地变量赋值,栈顶变量的值并没有进行自增操作,自增操作是对本地变量进行操作的)
对于 b = ++b; JVM 进行的操作是:
1. 将本地变量的值先自增
2. 将自增完之后的本地变量的值加载到栈顶(注意:这时候这个值是经过了自增操作的)
3. 将栈顶变量的值存储到本地变量中
Java中的自增问题(i=i++)的更多相关文章
- 【Java】【4】关于Java中的自增自减
摘要:理解j = j++与j = ++j的区别:正确用法:直接用j++,不要用前两种 正文: import java.util.*; public class Test{ public static ...
- java中的自增问题
运行下面这段代码,其结果是什么呢? package com.test; public class Inc { public static void main(String[] args) { Inc ...
- java中集合的增删改操作及遍历总结
集合的增删改操作及遍历总结
- java中双向链表的增、删、查操作
import java.util.NoSuchElementException; public class DoublyLinkedListImpl<E> { private Node h ...
- Java中的自增自减
情况①: for (int i = 0; i < 100; i++) { j = 1 + j++; } System.out.println(j); 结果是 0 !! 这是由于在进行后自增/自减 ...
- Java中AtomicInteger的使用!!!
今天在看Volley的源码的时候,看到里面使用了AtomicInteger这个类,曾经没用过,今天看了一下API学习了一下: 首先介绍一下这个类的用处,这个类主要是用来替换java中的自增和自减操作, ...
- Android(java)学习笔记186:对ListView等列表组件中数据进行增、删、改操作
1.ListView介绍 解决大量的相似的数据显示问题 采用了MVC模式: M: model (数据模型) V: view (显示的视图) C: controller 控制器 入门案例: acit ...
- Android(java)学习笔记129:对ListView等列表组件中数据进行增、删、改操作
1. ListView介绍 解决大量的相似的数据显示问题 采用了MVC模式: M: model (数据模型) V: view (显示的视图) C: controller 控制器 入门案例: aci ...
- java中如何理解:其他类型 + string 与 自增类型转换和赋值类型转换
java中如何理解:其他类型 + string 与 自增类型转换和赋值类型转换 一.字符串与其他类型连接 public class DemoString{ public static void mai ...
随机推荐
- [zz] ROC曲线
wiki https://zh.wikipedia.org/wiki/ROC%E6%9B%B2%E7%BA%BF 在信号检测理论中,接收者操作特征曲线(receiver operating chara ...
- mybatis实战教程(mybatis in action)之八:mybatis 动态sql语句
mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:1. if 语句 (简单的条件判断)2. c ...
- C#中的using关键字用法总结
C#中的using关键字主要有两种用法: 1.using作为指令: (1)用于将命名空间引入当前单元,例如:using System.Windows.Forms; (2)为现有的命名空间创建一个别名, ...
- web页面如何播放amr的音频文件
这个需求由来已久,公司的语音订单很多,每次客服都是从服务器down下语音来听.很不方便..于是我就上网扒拉看有么有什么web播放器能播放amr格式的音频文件,amr百度百科 总之找了很久.,,然后发现 ...
- NIO源码阅读
自己对着源码敲一遍练习,写上注释.发现NIO编程难度好高啊..虽然很复杂,但是NIO编程的有点还是很多: 1.客户端发起的连接操作是异步的,可以通过在多路复用器注册OP_CONNECTION等待后续结 ...
- Azure
ylbtech-Miscellaneos:Azure A,返回顶部 1, Windows Azure是微软基于云计算的操作系统,现在更名为“Microsoft Azure”,和Azure Servic ...
- sklearn学习笔记1
Image recognition with Support Vector Machines #our dataset is provided within scikit-learn #let's s ...
- java 对EXCEL表格的处理
都整蒙圈了 Cannot get a numeric value from a text cell 的处理,EXCEL表格里是数值型的处理 http://blog.csdn.net/ysughw/ar ...
- 尝试打开或创建物理文件 REATE FILE 遇到操作系统错误 5(拒绝访问)
尝试打开或创建物理文件 'E:\Library.mdf' 时,CREATE FILE 遇到操作系统错误 5(拒绝访问.). 最佳回答: 这是因为SQL Server的启动帐户(一般是system或某个 ...
- 双系统先装Windows,后装linux的原因
由于windows在安装时,boot loader会预设装在MBR及分割槽的boot sector中,而且并不提供开机选单:而linux在安装时安装程序可以选择是安装在MBR中还是boot secto ...