次のコードがあります:
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
- アップデート
バイトコードは次のとおりです:
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
}
私はについて読みます説明書理解しようと努める...
ベストアンサー1
注: もともとこの回答では、説明のためにC#コードを投稿しました。C#ではキーワードint
を使用して参照渡しでパラメータを渡せるからですref
。最初のコードを使用して、実際の合法的なJavaコードに更新することにしました。MutableInt
Google で見つけたクラスは、C# で行われることとほぼ同じですref
。これが回答に役立つか、害になるかはわかりません。個人的には 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