public class Test{
public static void main(String[] args){
int i=0;
int a=i++;
System.out.println(i);
System.out.println(a);
}
}
对于上述代码,发现一个朋友在讨论这个问题,今天仔细研究了一下,发现其中的问题还是很多的。
1.执行javap -c Test
E:\第二阶段练习文件\js\test>javap -c Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
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_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_2
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: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
17: iload_2
18: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
21: return
}
这是执行的结果,仔细研究这个反编译过程,并查找了一些资料,觉得应该是解决了这个问题。
2.谈谈体会:
开始的时候在栈中放入0,为i的引用。
然后计算i++,很明显,a的值为1,然后i为2.
当然这个谁都知道,那i=i++呢?如果是这个问题,就比较复杂了,但是想通了之后,你就知道我为什么要写上述的程序了。
来看看i=i++的程序:
public class Test{
public static void main(String[] args){
int i=0;
i=i++;
System.out.println(i);
}
}
执行反编译的结果:
E:\第二阶段练习文件\js\test>javap -c Test
Compiled from "Test.java"
public class Test extends java.lang.Object{
public Test();
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_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
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
}
结果是:
0
为什么呢?
首先,在栈中放入0
然后,将i=i++中的i++计算,可知,要将i=0这个值赋给
i=i++
中的前面的那个i,这就是java会给i分配一个新的虚拟空间来保存这个数据,而当后面的那个i计算为1之后,这个表达式就执行完毕,但是,此时,高潮来了。
前面的那个i中的值将会从栈中被取出并覆盖了后面的那个i,因为这里只许拥有一个i变量,后面的那个i本来是1,但是它的值在栈中被先取出来了,所以是开始为1,最后为0(这个0是由前面那个i放进去的)
|
|