本文翻譯自:Why does this go into an infinite loop?
I have the following code: 我有以下代碼:
public class Tests {
public static void main(String[] args) throws Exception {
int x = 0;
while(x<3) {
x = x++;
System.out.println(x);
}
}
}
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. 我們知道他應該只寫x++
或x=x+1
,但是在x = x++
它應該首先將x
歸屬於它自己,然後再增加它。 Why does x
continue with 0
as value? 爲什麼x
繼續爲0
作爲值?
--update --update
Here's the bytecode: 這是字節碼:
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... 我會讀到有關試圖理解的說明 ......
#1樓
參考:https://stackoom.com/question/G4hp/爲什麼會進入無限循環
#2樓
Check the below code, 檢查以下代碼,
int x=0;
int temp=x++;
System.out.println("temp = "+temp);
x = temp;
System.out.println("x = "+x);
the output will be, 輸出將是,
temp = 0
x = 0
post increment
means increment the value and return the value before the increment . post increment
意味着遞增值並在遞增之前返回值 。 That is why the value temp
is 0
. 這就是值temp
爲0
。 So what if temp = i
and this is in a loop (except for the first line of code). 那麼如果temp = i
並且這是一個循環(第一行代碼除外)。 just like in the question !!!! 就像在問題!!!!
#3樓
This statement: 這個說法:
x = x++;
evaluates like this: 評估如下:
- Push
x
onto the stack; 將x
推入堆棧; - Increment
x
; 增量x
; - Pop
x
from the stack. 從堆棧彈出x
。
So the value is unchanged. 所以價值沒有變化。 Compare that to: 比較一下:
x = ++x;
which evaluates as: 評估爲:
- Increment
x
; 增量x
; - Push
x
onto the stack; 將x
推入堆棧; - Pop
x
from the stack. 從堆棧彈出x
。
What you want is: 你想要的是:
while (x < 3) {
x++;
System.out.println(x);
}
#4樓
This is because it never gets incremented in this case. 這是因爲在這種情況下它永遠不會增加。 x++
will use the value of it first before incrementing like on this case it will be like: 在增加之前, x++
將首先使用它的值,就像在這種情況下它會像:
x = 0;
But if you do ++x;
但是如果你做++x;
this will increase. 這會增加。
#5樓
x = x++
works in the following way: x = x++
以下列方式工作:
- First it evaluates expression
x++
. 首先,它評估表達式x++
。 Evaluation of this expression produces an expression value (which is the value ofx
before increment) and incrementsx
. 對該表達式的求值產生表達式值(在遞增之前是x
的值)並且遞增x
。 - Later it assigns the expression value to
x
, overwriting incremented value. 稍後它將表達式值賦給x
,覆蓋遞增的值。
So, the sequence of events looks like follows (it's an actual decompiled bytecode, as produced by javap -c
, with my comments): 因此,事件序列如下所示(它是一個實際的反編譯字節碼,由javap -c
,帶有我的註釋):
8: iload_1 // Remember current value of x in the stack 9: iinc 1, 1 // Increment x (doesn't change the stack) 12: istore_1 // Write remebered value from the stack to x
For comparison, x = ++x
: 爲了比較, x = ++x
:
8: iinc 1, 1 // Increment x 11: iload_1 // Push value of x onto stack 12: istore_1 // Pop value from the stack to x
#6樓
This happens because the value of x
doesn't get incremented at all. 發生這種情況是因爲x
的值根本沒有增加。
x = x++;
is equivalent to 相當於
int temp = x;
x++;
x = temp;
Explanation: 說明:
Let's look at the byte code for this operation. 我們來看看這個操作的字節代碼。 Consider a sample class: 考慮一個示例類:
class test {
public static void main(String[] args) {
int i=0;
i=i++;
}
}
Now running the class disassembler on this we get: 現在運行類反彙編程序,我們得到:
$ javap -c test
Compiled from "test.java"
class test extends java.lang.Object{
test();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_0
1: istore_1
2: iload_1
3: iinc 1, 1
6: istore_1
7: return
}
Now the Java VM is stack based which means for each operation, the data will be pushed onto the stack and from the stack, the data will pop out to perform the operation. 現在Java VM是基於堆棧的,這意味着對於每個操作,數據將被推送到堆棧和堆棧,數據將彈出以執行操作。 There is also another data structure, typically an array to store the local variables. 還有另一種數據結構,通常是用於存儲局部變量的數組。 The local variables are given ids which are just the indexes to the array. 局部變量給出id,它們只是數組的索引。
Let us look at the mnemonics in main()
method: 讓我們看看main()
方法中的助記符 :
-
iconst_0
: The constant value0
is pushed on to the stack.iconst_0
:常量值0
被推入堆棧。 -
istore_1
: The top element of the stack is popped out and stored in the local variable with index1
istore_1
:彈出堆棧的頂部元素並將其存儲在索引爲1
的局部變量中
which isx
. 這是x
。 -
iload_1
: The value at the location1
that is the value ofx
which is0
, is pushed into the stack.iload_1
:位置1
的值x
是0
的值,被推入堆棧。 -
iinc 1, 1
: The value at the memory location1
is incremented by1
.iinc 1, 1
:存儲位置1
值增加1
。 Sox
now becomes1
. 所以x
現在變爲1
。 -
istore_1
: The value at the top of the stack is stored to the memory location1
.istore_1
:堆棧頂部的值存儲在內存位置1
。 That is0
is assigned tox
overwriting its incremented value. 將0
指定給x
覆蓋其遞增的值。
Hence the value of x
does not change resulting in the infinite loop. 因此, x
的值不會改變,從而導致無限循環。