我有以下代码:
public class Tests {
public static void main(String[] args) throws Exception {
int x = 0;
while(x<3) {
x = x++;
System.out.println(x);
}
}
}
我们知道他应该只写x++或x=x+1,但在x=x+ +时,它应该先把x归为自己,然后再加1。为什么x的值是0 ?
- - -更新
下面是字节码:
public class Tests extends java.lang.Object{
public Tests();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]) throws java.lang.Exception;
Code:
0: iconst_0
1: istore_1
2: iload_1
3: iconst_3
4: if_icmpge 22
7: iload_1
8: iinc 1, 1
11: istore_1
12: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
15: iload_1
16: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
19: goto 2
22: return
}
我会仔细阅读说明,试着理解……
你有效地得到了以下行为。
获取x的值(它是0)作为右边的“结果”
增加x的值(x现在是1)
将右边的结果(保存为0)分配给x (x现在是0)
其思想是,后增量操作符(x++)在返回变量的值后对该变量进行增量,以便在使用该变量的方程中使用。
编辑:由于评论的原因,稍微增加了一点。像下面这样考虑。
x = 1; // x == 1
x = x++ * 5;
// First, the right hand side of the equation is evaluated.
==> x = 1 * 5;
// x == 2 at this point, as it "gave" the equation its value of 1
// and then gets incremented by 1 to 2.
==> x = 5;
// And then that RightHandSide value is assigned to
// the LeftHandSide variable, leaving x with the value of 5.
你有效地得到了以下行为。
获取x的值(它是0)作为右边的“结果”
增加x的值(x现在是1)
将右边的结果(保存为0)分配给x (x现在是0)
其思想是,后增量操作符(x++)在返回变量的值后对该变量进行增量,以便在使用该变量的方程中使用。
编辑:由于评论的原因,稍微增加了一点。像下面这样考虑。
x = 1; // x == 1
x = x++ * 5;
// First, the right hand side of the equation is evaluated.
==> x = 1 * 5;
// x == 2 at this point, as it "gave" the equation its value of 1
// and then gets incremented by 1 to 2.
==> x = 5;
// And then that RightHandSide value is assigned to
// the LeftHandSide variable, leaving x with the value of 5.
从http://download.oracle.com/javase/tutorial/java/nutsandbolts/op1.html
The increment/decrement operators can
be applied before (prefix) or after
(postfix) the operand. The code
result++; and ++result; will both end
in result being incremented by one.
The only difference is that the prefix
version (++result) evaluates to the
incremented value, whereas the
postfix version (result++) evaluates
to the original value. If you are
just performing a simple
increment/decrement, it doesn't really
matter which version you choose. But
if you use this operator in part of a
larger expression, the one that you
choose may make a significant
difference.
为了说明这一点,请尝试以下方法:
int x = 0;
int y = 0;
y = x++;
System.out.println(x);
System.out.println(y);
它会输出1和0。
据我所知,错误发生了,由于赋值覆盖了增量值,在增量之前的值,即它取消了增量。
具体来说,"x++"表达式在递增前的值为'x',而"++x"表达式在递增后的值为'x'。
如果你对研究字节码感兴趣,我们将看一下有问题的三行:
7: iload_1
8: iinc 1, 1
11: istore_1
7: iload_1 #将第二个本地变量的值放在堆栈上
8: iinc 1,1 #将使第二个局部变量加1,注意它不影响堆栈!
9: istore_1 #将弹出堆栈顶部,并将该元素的值保存到第二个局部变量中
(你可以在这里阅读每条JVM指令的效果)
这就是为什么上面的代码将无限循环,而带有++x的版本不会。
++x的字节码应该看起来很不一样,据我所知,在我一年多以前写的1.3 Java编译器中,字节码应该是这样的:
iinc 1,1
iload_1
istore_1
所以只是交换了前两行,改变了语义,使得留在堆栈顶部的值,在增量之后(即表达式的“值”)是增量之后的值。