问题描述
我有以下代码:
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
归属于自身,然后再增加它。为什么 x
继续 0
作为值?
We know he should have writen just x++
or x=x+1
, but on x = x++
it should first attribute x
to itself, and later increment it. Why does x
continue with 0
as value?
- 更新
以下是字节码:
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
}
我会读到有关尝试理解......
I'll read about the instructions to try to understand...
推荐答案
注意:我最初发布了C#代码在本答案中,为了便于说明,因为C#允许您通过 ref
关键字引用传递 int
参数。我决定使用第一个类似于 ref
所做的近似C#。我无法确定这是否有助于或伤害答案。我会说我个人没有做过那么多的Java开发;所以我知道可能会有更多惯用的方法来说明这一点。
Note: Originally I posted C# code in this answer for purposes of illustration, since C# allows you to pass int
parameters by reference with the ref
keyword. I've decided to update it with actual legal Java code using the first MutableInt
class I found on Google to sort of approximate what ref
does in C#. I can't really tell if that helps or hurts the answer. I will say that I personally haven't done all that much Java development; so for all I know there could be much more idiomatic ways to illustrate this point.
也许如果我们写出一个方法做相当于什么 x ++
它会使这个更清楚。
Perhaps if we write out a method to do the equivalent of what x++
does it will make this clearer.
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
对吗?递增传递的值并返回原始值:这是postincrement运算符的定义。
Right? Increment the value passed and return the original value: that's the definition of the postincrement operator.
现在,让我们看一下示例代码中这种行为是如何发生的:
Now, let's see how this behavior plays out in your example code:
MutableInt x = new MutableInt();
x = postIncrement(x);
postIncrement(x)
做什么?增量 x
,是的。然后在增量之前返回 x
。然后将此返回值分配给 x
。
postIncrement(x)
does what? Increments x
, yes. And then returns what x
was before the increment. This return value then gets assigned to x
.
因此分配给的值的顺序x
是0,然后是1,然后是0。
So the order of values assigned to x
is 0, then 1, then 0.
如果我们重写上述内容,这可能会更清楚:
This might be clearer still if we re-write the above:
MutableInt x = new MutableInt(); // x is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
x = temp; // Now x is 0 again.
当您更换 x
在 y
的上述作业的左侧,你可以看到它首先递增x,然后将它归属为y让我感到困惑。分配给 y
的 x
不是;它以前分配给 x
的值。真的,注入 y
使得与上面的场景没有什么不同;我们只是得到:
Your fixation on the fact that when you replace x
on the left side of the above assignment with y
, "you can see that it first increments x, and later attributes it to y" strikes me as confused. It is not x
that is being assigned to y
; it is the value formerly assigned to x
. Really, injecting y
makes things no different from the scenario above; we've simply got:
MutableInt x = new MutableInt(); // x is 0.
MutableInt y = new MutableInt(); // y is 0.
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
y = temp; // y is still 0.
所以很清楚: x = x ++
实际上不会改变x的值。它总是使x具有值x ,然后x + 1,然后再次x 。
So it's clear: x = x++
effectively does not change the value of x. It always causes x to have the values x, then x + 1, and then x again.
更新:顺便提一下,以免你怀疑 x
在上面的例子中,我们将增量操作和赋值分配到1之间,我已经将一个快速演示组合在一起来说明这个中间值确实存在,尽管它在执行线程中永远不会被看到 。
Update: Incidentally, lest you doubt that x
ever gets assigned to 1 "between" the increment operation and the assignment in the example above, I've thrown together a quick demo to illustrate that this intermediate value does indeed "exist," though it will never be "seen" on the executing thread.
演示在一个循环中调用 x = x ++;
,而另一个线程连续打印<$的值c $ c> x 到控制台。
The demo calls x = x++;
in a loop while a separate thread continuously prints the value of x
to the console.
public class Main {
public static volatile int x = 0;
public static void main(String[] args) {
LoopingThread t = new LoopingThread();
System.out.println("Starting background thread...");
t.start();
while (true) {
x = x++;
}
}
}
class LoopingThread extends Thread {
public @Override void run() {
while (true) {
System.out.println(Main.x);
}
}
}
以下是摘录以上程序的输出。注意1和0的不规则出现。
Below is an excerpt of the above program's output. Notice the irregular occurrence of both 1s and 0s.
Starting background thread...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1
这篇关于为什么这会进入无限循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!