为了账号安全,请及时绑定邮箱和手机立即绑定

为什么会进入无限循环?

为什么会进入无限循环?

手掌心 2019-09-18 11:16:48
我有以下代码: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:   returnpublic 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}我会读到有关试图理解的说明 ......
查看完整描述

3 回答

?
牛魔王的故事

TA贡献1830条经验 获得超3个赞

注意:最初我在本答案中发布了C#代码用于说明,因为C#允许您int通过引用传递参数和ref关键字。我决定使用MutableInt我在Google上找到的第一个类来实际使用合法的Java代码来更新它,以便对refC#中的内容进行近似处理。我无法确定这是否有助于或伤害答案。我会说我个人没有做过那么多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.

当你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。


更新:顺便说一句,为了避免你怀疑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


查看完整回答
反对 回复 2019-09-18
  • 3 回答
  • 0 关注
  • 697 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信