java – 为什么会进入无限循环?

我有以下代码:

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

}

我会读到关于instructions试图了解…

解决方法:

注意:最初我在本答案中发布了C#代码用于说明,因为C#允许您通过ref关键字引用传递int参数.我决定使用我在Google上找到的第一个MutableInt类来使用实际的合法Java代码更新它,以便对C#中的ref进行排序.我无法确定这是否有助于或伤害答案.我会说我个人没有做过那么多Java开发;所以我知道可能有更多的惯用方法来说明这一点.

也许如果我们写出一个方法来做相当于x的方法,它会使这个更清楚.

public MutableInt postIncrement(MutableInt x) {
    int valueBeforeIncrement = x.intValue();
    x.add(1);
    return new MutableInt(valueBeforeIncrement);
}

对?增加传递的值并返回原始值:这是postincrement运算符的定义.

现在,让我们看看您的示例代码中这种行为是如何发挥作用的:

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.

你固定的事实是,当你用y替换上面赋值左侧的x时,“你可以看到它首先递增x,然后将它归属为y”让我感到困惑.它不是分配给y的x;它是以前分配给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的值为x0,然后是x0 1,然后是x0.

更新:顺便说一句,为了避免你怀疑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的不规则出现.

Starting background thread...
0
0
1
1
0
0
0
0
0
0
0
0
0
0
1
0
1
上一篇:用PHP中的@运算符抑制错误


下一篇:python – 如何覆盖NumPy的ndarray和我的类型之间的比较?