注:C#ではキーワードintを使用して参照によってパラメーターを渡すことができるため、最初は説明のためにこの回答にC#コードを投稿しました。ref私はMutableInt、Google で見つけた最初のクラスを使用して、実際の合法的な Java コードで更新しrefて、C# での動作を近似することにしました。それが答えを助けるか傷つけるかは本当にわかりません。個人的には、Java 開発はあまり行っていません。したがって、私が知っている限りでは、この点を説明するもっと慣用的な方法があるかもしれません.
おそらく、それが行うことと同等のことを行うメソッドを書き出すx++と、これがより明確になるでしょう。
public MutableInt postIncrement(MutableInt x) {
int valueBeforeIncrement = x.intValue();
x.add(1);
return new MutableInt(valueBeforeIncrement);
}
右?渡された値をインクリメントし、元の値を返します。これがポストインクリメント演算子の定義です。
それでは、サンプル コードでこの動作がどのように実行されるかを見てみましょう。
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 の値が x 0になり、次に x 0 + 1、そして再びx 0になります。
更新:ちなみに、上記の例のインクリメント操作と割り当ての「間」で 1 に割り当てられることを疑うxために、この中間値が実際に「存在する」ことを示す簡単なデモをまとめました。実行中のスレッドで「見られる」ことはありません。
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 の両方が不規則に発生することに注意してください。
バックグラウンド スレッドを開始しています...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1