初学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 atestCompiled from "atest.java"public class atest { public atest(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: returnpublic 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.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 42: iload_1 43: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 46: ldc #8 // String ; m= 48: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 51: iload_2 52: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 55: ldc #9 // String ; n= 57: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 60: iload_3 61: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 64: ldc #10 // String ; p= 66: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 69: iload 4 71: invokevirtual #7 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 74: invokevirtual #11 // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 77: invokevirtual #12 // Method java/io/PrintStream.println:(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此时变成215: 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); }}