Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 0ae910d

Browse files
committed
finished translating Why does this go into an infinite loop?
1 parent ca5550b commit 0ae910d

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
## 这段代码为什么陷入了死循环
2+
3+
### 问题
4+
我写了这样一段代码
5+
6+
```java
7+
public class Tests {
8+
public static void main(String[] args) throws Exception {
9+
int x = 0;
10+
while(x<3) {
11+
x = x++;
12+
System.out.println(x);
13+
}
14+
}
15+
}
16+
```
17+
18+
我们知道他应该只写x++或者x=x+1就行了,但是x=x++的情况下,x应该先赋值给自己,然后再增加1。为什么X的值一直是0呢?
19+
20+
--更新
21+
</br>下面是字节码
22+
23+
```java
24+
public class Tests extends java.lang.Object{
25+
public Tests();
26+
Code:
27+
0: aload_0
28+
1: invokespecial #1; //Method java/lang/Object."<init>":()V
29+
4: return
30+
31+
public static void main(java.lang.String[]) throws java.lang.Exception;
32+
Code:
33+
0: iconst_0
34+
1: istore_1
35+
2: iload_1
36+
3: iconst_3
37+
4: if_icmpge 22
38+
7: iload_1
39+
8: iinc 1, 1
40+
11: istore_1
41+
12: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
42+
15: iload_1
43+
16: invokevirtual #3; //Method java/io/PrintStream.println:(I)V
44+
19: goto 2
45+
22: return
46+
47+
}
48+
```
49+
50+
51+
### 回答
52+
53+
一开始我用C#代码来解释,因为C#允许用"ref"关键字来实现int参数的引用传递,所以我决定用我google到的MutableInt类写的标准的java代码来模拟C#中ref关键字作用.我不知道这对我的解答是不是有帮助,我并不是一个专业的java开发者,我知道还有很多更符合语言习惯的方法去解释这个问题。
54+
也许我写一个函数来模拟x++的作用会解释得更清楚
55+
56+
```java
57+
public MutableInt postIncrement(MutableInt x) {
58+
int valueBeforeIncrement = x.intValue();
59+
x.add(1);
60+
return new MutableInt(valueBeforeIncrement);
61+
}
62+
```
63+
64+
对不对?将传递的参数值加1然后返回原值,这就是后增操作符的定义。
65+
现在让我们看看在你的代码中是怎么执行的。
66+
67+
```java
68+
MutableInt x = new MutableInt();
69+
x = postIncrement(x);
70+
```
71+
72+
`postIncrement(x)`函数做了什么?x增加1,对,然后返回x加1之前的值,并且把该返回值赋给x。所以X被赋值的顺序是0,1,0。如果我们重写上面的代码会理解得更清楚。
73+
74+
```java
75+
MutableInt x = new MutableInt(); // x is 0.
76+
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
77+
x = temp; // Now x is 0 again.
78+
```
79+
80+
你定势地认为,将左边的X换个名称为y,"你能看到x先自增1,然后赋值给了y",这一时也让我有点困惑。bi那个不是x被赋值给y,而是x(自增)之前的值被赋给y.事实上,把左边x变量名改成y结果也没什么不同。
81+
82+
```java
83+
MutableInt x = new MutableInt(); // x is 0.
84+
MutableInt y = new MutableInt(); // y is 0.
85+
MutableInt temp = postIncrement(x); // Now x is 1, and temp is 0.
86+
y = temp; // y is still 0.
87+
```
88+
89+
可见,x=x++并没有改变x的值,只是让x依次被赋值为x0,x0+1,x0。
90+
91+
更新:你可能会怀疑在自增过程中x并没有被赋值为1,下面通过一个demo来解释确实x存在赋值为1的过程。
92+
demo中调用了x=x++;同时另外开了一个单独的线程不断输出x的值.
93+
94+
```java
95+
public class Main {
96+
public static volatile int x = 0;
97+
98+
public static void main(String[] args) {
99+
LoopingThread t = new LoopingThread();
100+
System.out.println("Starting background thread...");
101+
t.start();
102+
103+
while (true) {
104+
x = x++;
105+
}
106+
}
107+
}
108+
109+
class LoopingThread extends Thread {
110+
public @Override void run() {
111+
while (true) {
112+
System.out.println(Main.x);
113+
}
114+
}
115+
}
116+
```
117+
118+
下面是程序的部分输出,0和1不规则的出现。
119+
120+
```
121+
Starting background thread...
122+
0
123+
0
124+
1
125+
1
126+
0
127+
0
128+
0
129+
0
130+
0
131+
0
132+
0
133+
0
134+
0
135+
0
136+
1
137+
0
138+
1
139+
```
140+
141+
142+
stackoverflow链接:
143+
[http://stackoverflow.com/questions/3831341/why-does-this-go-into-an-infinite-loop](http://stackoverflow.com/questions/3831341/why-does-this-go-into-an-infinite-loop)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /