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

首先看下面一个小程序:

  1. public class atest{
  2.  
  3. public static void main(String args[]){
  4. int s=1,m=1,n=1,p=1;
  5. s++;
  6. ++m;
  7. n=n++;
  8. p=++p;
  9. System.out.println("s="+s+"; m="+m+"; n="+n+"; p="+p);
  10. }
  11. }

输出为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的栈顶值也就是计算后的值。

扩展练习:

  1. public class atest{
  2.  
  3. public static void main(String args[]){
  4. int s=0,m=0,n=0,p=0;
  5. for(int i=0;i<100;i++){
  6. s++;
  7. ++m;
  8. n=n++;
  9. p=++p;
  10. }
  11. System.out.println("s="+s+"; m="+m+"; n="+n+"; p="+p);
  12. }
  13. }

随机推荐

  1. Jmeter实现MD5加密

    Jmeter3.0以后的版本不再内置MD5加密函数,只能自己写了. 1.编码 package com.liuke.test; import java.security.MessageDigest; i ...

  2. ES6解构赋值

    前面的话 我们经常定义许多对象和数组,然后有组织地从中提取相关的信息片段.在ES6中添加了可以简化这种任务的新特性:解构.解构是一种打破数据结构,将其拆分为更小部分的过程.本文将详细介绍ES6解构赋值 ...

  3. 【ES6】变量的解构赋值

    1. 数组 var [a, b, c] = [1, 2, 3]; let [a, [b], d] = [1, [2, 3], 4]; 默认值生效的条件是,对象的属性值严格等于undefined. [x ...

  4. Java复习随笔

    1.StringTokenizer str = new StringTokenizer("字符串"); str.countTokns();   //可得出字符串非连续的个数(可用于 ...

  5. 如何自己写一个公用的NPM包

    以markdown-clear,创建过程为例,讲解整个NPM包创建和发布流程 1 如何创建一个包 1.1 创建并使用一个工程 在GitHub上新建一个仓库,其名markdown-clear clone ...

  6. hdu--3782--找规律--xxx定律

    /* Name: hdu--3782--xxx定律 Date: 17/04/17 21:34 Description: 找规律题,又想打表了 */ /* for(int i=2;i<30;++i ...

  7. MySQL xtrabackup之--databases 勿手贱

    xtrabackup备份单库时,必须指定--databases,但是如果将databases写成了database,那么xtrabackup备份的就是整个数据库,以下是 uuid = 397ae42e ...

  8. 1.怎样控制div中的图片居中

    答案如下: #div{ width: 100%; height: 100%; border: 1px solid #000; text-align: center;}#div img{ vertica ...

  9. ES6 浅谈let与const 块级作用域之封闭空间(闭包)

    ES6新增了 let const 命令,用来声明变量.它的用法类似于 var  ,但是所声明的变量,只在 let const 命令所在的代码块内有效.  var const 不允许重复声明 用处: 可 ...

  10. HTML indexedDB数据库—简单示例

    indexedDB数据库的基本概念:在HTML5中,新增一种被称为"indexedDB"的数据库,该数据库是一种存储在客户端本地的NoSQL数据库. <!DOCTYPE ht ...