大家看一下下面一个程序:
一、问题说明
Test.java
public class Test { public static void main(String[] args) { int i = 1; i = ++i; System.out.println(i); } }
输出:2,这应该没有异议对吧,那么再看一个程序
Test1.java
public class Test1 { public static void main(String[] args) { int i = 1; i = i++; System.out.println(i); } }
输出:1。有点意思了吧~
问题解答
其实这是因为java解析器在生成class文件的不一致造成的。
使用javap -verbose Test 查看内容(代码片段):
public static void main(java.lang.String[]); Code: Stack=2, Locals=2, Args_size=1 0: iconst_1 //将1推送到栈顶 1: istore_1 //将栈顶的内容赋值给第二个变量i,注意此时栈顶的内容是:1 2: iinc 1, 1 //执行加一操作 5: iload_1 //将变量i的内容推送到栈顶 6: istore_1 //将栈顶的内容保存到变量i 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
使用 javap -verbose Test1查看内容(代码片段):
public static void main(java.lang.String[]); Code: Stack=2, Locals=2, Args_size=1 0: iconst_1 1: istore_1 2: iload_1 //将变量i的内容推送到栈顶,不知道为什么这么生成字节码!注意此时栈顶的内容是:1 3: iinc 1, 1 //执行加一操作 6: istore_1 //将栈顶的内容保存到变量i 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
发现少了一个iload_1,意思是将变量推送至栈顶,结果i=i++;命令虽然执行了加i+1的操作但是没有保存回到变量i中。
命令说明:
- iconst_1 将int型1推送至栈顶
- istore_1 将栈顶int型数值存入第二个本地变量
- iload_1 将第二个int型本地变量推送至栈顶(正是因为少了这个操作,才出现以上问题)
- iinc 将指定int型变量增加指定值(i++, i--, i+=2)