[解決済み] なぜ無限ループになるのですか?
質問
次のようなコードがあります。
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
を値とするか?
--update
以下はバイトコードです。
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
}
を読んでみる。 指示 を理解しようとすると...。
解決方法は?
注意事項
: 元々、この回答では説明のためにC#のコードを掲載しましたが、これはC#では
int
という参照によるパラメータがあります。
ref
というキーワードがあります。を使って、実際に合法的なJavaコードで更新することにしたのですが、最初の
MutableInt
を近似するために、Googleで見つけた
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 の値を変更することはありません。
<サブ
0
の場合、x
<サブ
0
+ 1 となり、x
<サブ
0
をもう一度。
更新情報
: ちなみに、疑われないように
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の両方が不規則に出現していることに注目してください。
バックグラウンドスレッドの起動... 0 0 1 1 0 0 0 0 0 0 0 0 0 0 1 0 1
関連
-
Java エラー報告 スレッド "main" での例外 java.util.NoSuchElementException
-
テストが見つかりませんでした
-
[解決済み] この2回(1927年)を引き算すると、なぜおかしな結果になるのでしょうか?
-
[解決済み] JavaでInputStreamを読み込んでStringに変換するにはどうすればよいですか?
-
[解決済み] JavaScriptのオブジェクトをループスルーまたは列挙するにはどうすればよいですか?
-
[解決済み] B "の印刷が "#"の印刷より劇的に遅いのはなぜですか?
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み】Pythonに三項条件演算子はありますか?
-
[解決済み] リファレンス - このシンボルはPHPで何を意味するのですか?
-
[解決済み】なぜJavaの+=, -=, *=, /=複合代入演算子はキャスティングを必要としないのですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Java のエラーです。未解決のコンパイル問題 解決方法
-
Android Studio 3.1.2 で v4, v7 パッケージが見つからない シンボル 'AppCompatActivity' を解決できない
-
eclipseにプロジェクトをインポートした後、Editorにmain typeが含まれない問題
-
リソースの読み込みに失敗しました。サーバーはステータス500(内部サーバーエラー)で応答しました。
-
が 'X-Frame-Options' を 'deny' に設定しているため、フレーム内にある。
-
javaでよく使われる英単語
-
あるコードに出会いましたが、何に使うのか理解できません。 List<String> list = new ArrayList<String>() { { a
-
ローカルリソースのロードが許可されていない場合の解決策
-
[解決済み] x--やx++はここで何をするのですか?
-
[解決済み】「x = x++」の後のxは何ですか?