初学Java,经常看到i++和++i的一些问题,在此整理一下。

首先看下面一个小程序:

public class atest{

    public static void main(String args[]){
int s=1,m=1,n=1,p=1;
s++;
++m;
n=n++;
p=++p;
System.out.println("s="+s+"; m="+m+"; n="+n+"; p="+p);
}
}

输出为s=2; m=2; n=1; p=2

这里比较难以理解的应该是n的值,下面我们对程序进行反编译进行分析:

E:\test>javap -c atest
Compiled from "atest.java"
public class atest {
public atest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":
()V
4: return

public static void main(java.lang.String[]);
Code:
0: iconst_1
1: istore_1
2: iconst_1
3: istore_2
4: iconst_1
5: istore_3
6: iconst_1
7: istore 4
9: iinc 1, 1
12: iinc 2, 1
15: iload_3
16: iinc 3, 1
19: istore_3
20: iinc 4, 1
23: iload 4
25: istore 4
27: getstatic #2 // Field java/lang/System.out:Ljava/
io/PrintStream;
30: new #3 // class java/lang/StringBuilder
33: dup
34: invokespecial #4 // Method java/lang/StringBuilder."<
init>":()V
37: ldc #5 // String s=
39: invokevirtual #6 // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
42: iload_1
43: invokevirtual #7 // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
46: ldc #8 // String ; m=
48: invokevirtual #6 // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
51: iload_2
52: invokevirtual #7 // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
55: ldc #9 // String ; n=
57: invokevirtual #6 // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
60: iload_3
61: invokevirtual #7 // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
64: ldc #10 // String ; p=
66: invokevirtual #6 // Method java/lang/StringBuilder.ap
pend:(Ljava/lang/String;)Ljava/lang/StringBuilder;
69: iload 4
71: invokevirtual #7 // Method java/lang/StringBuilder.ap
pend:(I)Ljava/lang/StringBuilder;
74: invokevirtual #11 // Method java/lang/StringBuilder.to
String:()Ljava/lang/String;
77: invokevirtual #12 // Method java/io/PrintStream.printl
n:(Ljava/lang/String;)V
80: return
}

对相关部分进行分析,注释如下:

0: iconst_1                       //把1放到栈顶
1: istore_1                       //把栈顶的值放到局部变量1中,即s
2: iconst_1                       //把1放到栈顶
3: istore_2                       //把栈顶的值放到局部变量2中,即m
4: iconst_1                       //把1放到栈顶
5: istore_3                       //把栈顶的值放到局部变量3中,即n
6: iconst_1                       //把1放到栈顶
7: istore 4                        //把栈顶的值放到局部变量4中,即p
9: iinc 1, 1                       //把局部变量1(也就是s),增加1,这个指令不会导致栈的变化,s此时变成2
12: iinc 2, 1                     //把局部变量2(也就是m),增加1,这个指令不会导致栈的变化,m此时变成2
15: iload_3                      //把局部变量3(也就是n)的值放到栈顶,此时栈顶为1
16: iinc 3, 1                     //把局部变量3(也就是n),增加1
19: istore_3                     //把栈顶的值放到局部变量3(也就是n)中
20: iinc 4, 1                     //把局部变量4(也就是p),增加1
23: iload 4                       //把局部变量4(也就是p)的值放到栈顶,此时栈顶为2
25: istore 4                      //把栈顶的值放到局部变量4(也就是p)中

由此看见,i=i++是先将i的值放到栈顶,而后对i进行操作,最后返回给i的栈顶值还是先前的值,而i=++i是先对i进行操作,然后将i的值放到栈顶,最后返回给i的栈顶值也就是计算后的值。

扩展练习:

public class atest{

    public static void main(String args[]){
int s=0,m=0,n=0,p=0;
for(int i=0;i<100;i++){
s++;
++m;
n=n++;
p=++p;
}
System.out.println("s="+s+"; m="+m+"; n="+n+"; p="+p);
}
}

随机推荐

  1. python数据结构之队列

    队列(queue)是只允许在一端进行插入操作,而在另一端进行删除操作的线性表. 队列是一种先进先出的(First In First Out)的线性表,简称FIFO.允许插入的一端为队尾,允许删除的一端 ...

  2. 回味Python2.7——笔记3

    一.错误和异常 1.异常处理 >>> while True: ... try: ... x = int(raw_input("Please enter a number: ...

  3. 第一章之s5pv210启动顺序

    我所使用的开发板是:友善之臂smart210,cpu为s5pv210.u-boot版本是:u-boot-2012-10 1,首先在u-boot中配置相对应的开发板的配置文件 #make s5p_gon ...

  4. zabbix 配置发送邮件报警

    标签:监控/SQLServer/Windows 概述 本篇文章主要介绍如何配置zabbix借助外部邮件进行发送邮件报警,zabbix通过配置文件调用mailx来进行邮件的发送.在Centos6以上的版 ...

  5. Angular页面加载后自动弹窗

    首先在控制器内写好一个弹窗,我用的是ionic的默认提示对话框 // 一个确认对话框 $scope.showConfirm = function() { var confirmPopup = $ion ...

  6. year:2017 month:08 day:04

    2017-08-04 JAVAse 1.final修饰符 final可以修饰类,成员方法,成员变量(static 修饰符不可以修饰类) final的初始化在对象被实例化前即可final 修饰的方法不可 ...

  7. 独立ip的优势

    独立ip的建站优势   我想很多人都想知道,那我就在这里给大家简单介绍下独立ip的优势有那些.                    网站设计是需要很多专业知识的结合,整站不是那么容易就可以设计完成的 ...

  8. 利用dbutils工具实现数据的增删查改操作(dbutis入门)

    一.前期准备 1.安装数据库(如:mysql5.5) 2.安装Eclipse(如:3.4) 3.下载数据库驱动包 4.下载dbutis工具包 5.在Eclipse创建名为 dbutils 的工程并在工 ...

  9. 实例甜点 Unreal Engine 4迷你教程(5)之函数中的静态变量

    本小节的教程无前置教程,可直接学习,篇幅很短. 本教程浓缩起来就是一句话:函数中的静态变量在调试过程中保留值.所以需要谨慎对待. 什么意思?请先不要一步一步对着做,而整体地看一遍下面的过程: 第一步: ...

  10. Java Web开发 - 持久型/存储型XSS漏洞

    Java Web开发 - 持久型/存储型XSS漏洞 1.什么是XSS漏洞攻击? XSS是跨站脚本攻击(Cross Site Scripting)的简称,之所以叫XSS而不是CSS相比大家都能明白了吧, ...