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++所做的事情,就会更清楚。
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
对吧?对传递的值加1并返回原始值:这就是后加1操作符的定义。
现在,让我们看看这个行为是如何在你的示例代码中发挥作用的:
MutableInt x = new MutableInt();
x = postIncrement(x);
postIncrement(x)做什么?增量x,对。然后返回x在增量之前的值。然后这个返回值被赋值给x。
所以x的值的顺序是0,然后是1,然后是0。
如果我们重写上面的代码,这可能会更清楚:
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”,这让我很困惑。不是x被赋值给y;它是以前赋给x的值。实际上,注入y与上面的场景没有什么不同;我们得到:
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的值为x0,然后是x0 + 1,然后又是x0。
更新:顺便说一句,为了避免您怀疑x在增量操作和上面示例中的赋值之间被赋值为1,我已经组合了一个快速演示来说明这个中间值确实“存在”,尽管它永远不会在执行线程上“看到”。
演示调用x = x++;在循环中,另一个线程连续地将x的值打印到控制台。
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的不规则出现。
Starting background thread...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1