Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
j+;=j++;你喜欢Java吗?_Java - Fatal编程技术网

j+;=j++;你喜欢Java吗?

j+;=j++;你喜欢Java吗?,java,Java,有人能给我解释一下这种行为吗? 首先,我认为答案是511+512(如果j+=j++意味着j=j+(j+1)) 我如何证明答案为零 public class Test { public static void main(String[] args) { int i = 0; int j = 0; for (i = 0, j = 0; i < 10; i++) { j += j++;

有人能给我解释一下这种行为吗?
首先,我认为答案是511+512(如果j+=j++意味着j=j+(j+1))
我如何证明答案为零

public class Test
{
    public static void main(String[] args)
    {
        int i = 0;
        int j = 0;
        for (i = 0, j = 0; i < 10; i++) 
        {
            j += j++;
            System.out.println("i = " + i +  " >> " + j);
        }
        System.out.println(j);
    }
}

> java Test
i = 0 >> 0
i = 1 >> 0
i = 2 >> 0
i = 3 >> 0
i = 4 >> 0
i = 5 >> 0
i = 6 >> 0
i = 7 >> 0
i = 8 >> 0
i = 9 >> 0
0
公共类测试
{
公共静态void main(字符串[]args)
{
int i=0;
int j=0;
对于(i=0,j=0;i<10;i++)
{
j++=j++;
System.out.println(“i=“+i+”>>”+j);
}
系统输出println(j);
}
}
>java测试
i=0>>0
i=1>>0
i=2>>0
i=3>>0
i=4>>0
i=5>>0
i=6>>0
i=7>>0
i=8>>0
i=9>>0
0
问题就在这里

j += j++;
开始时,
j=0
,然后
j++
表示
j
将在下一次迭代中递增。但是,在下一次迭代之前,您将
0
分配到
j

因此
j
被重新分配到
0

因为
j++
表示求值后的增量,
j+=x
表示
j=j+x
,所以
j
在求值
j=j+j
后变为
j+1
,求值后为零(加法结果为0),计算此加法后,j增加j++,但在此之后,加法结果将覆盖增加的j值,其值为0

看看这个,假设j=0

j += j++
读取
j
值后,将执行
j++
增量,该值目前为
0

因此,它可以转化为:

   1) read the first value for add operation - the value of j is 0 so we have add(0, ?)
   2) read the second value for add operation `j++` is first evaluated to 0
      so we have now add(0,0), 
      then j is incremented by 1, but it has this value for a very short time:
   3) execute the add(0,0) operation, the result is 0 and overrides the incrementation done in previous setep.
   4) finally the j is 0
因此,在这种情况下,j在很短的时间内变成1,但之后很快就会被覆盖

结论是:数学上
j++=j++最终变成仅
j=j+j

在for循环中,这种情况会重复每一次循环执行,最初j是0,因此它永远保持这种状态,在每次循环运行中都会在很短的时间内闪烁到1

也许你可以让j变得易变,然后在这个
j++=j++的计算过程中,由另一个线程在循环中读取它。阅读线程可能会看到j暂时变成1,但这是不确定的,在我的例子中,我使用这个简单的测试程序看到了这种情况:

public class IncrementationTest {

    public static void main(String[] args) {
        new IncrementationTest().start();
    }

    private volatile int j;

    private void start() {
        new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println(j);
                }
            }
        }.start();

        while (true) {
            j += j++;
        }

    }

}
输出为:

...
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
...
在我的机器上,似乎经常有幸读取中间值1来计算
j++=j++

后增量运算符的作用是什么?操作完成后的增量

现在
j++=j++

当将
j
添加到
j
时,此处的
j
0
。因此
0+=0
将成为
0

该值超出限制,因此
j
将永远保持
0

现在让我们尝试使用预增量

j++=++j

输出:

i = 0 >> 1 // 0 + 1
i = 1 >> 3 // 1 + 2
i = 2 >> 7 // 3 + 4
i = 3 >> 15
i = 4 >> 31
i = 5 >> 63
i = 6 >> 127
i = 7 >> 255
i = 8 >> 511
i = 9 >> 1023

有意义吗?

因为当您执行
a=b+c
时,您首先读取
b
c
,然后计算值

另外,
j++
表示返回j的当前值,然后将其递增1

在您的情况下,由于执行了
j=j+j++
操作,您首先读取
j
,然后再次读取
j
,并返回
j
的值。让我们以第一次迭代为例:

  • 你读j=0
  • 你又读了一次j=0
  • 计算
    j=j+1
  • 但是,现在计算j=0+0并覆盖该值

  • 因此,在迭代结束时,
    j
    的值没有改变。还是0。每一次迭代都是如此,这就是为什么
    j
    的值永远不会改变的原因。

    出现这个问题的原因是,如果在语句中使用“j++”,它的工作格式如下-

  • 首先,在语句中使用
    j
    的值
  • 然后增加
    j
    的值
  • 在您的情况下,当您执行
    j++=j++
    时,发生的是-

  • 首先,语句中使用了
    j
    的值,因此
    j++
    返回要在语句中使用的
    0
    ,我们计算了要分配给
    j
    (尚未分配)的
    0+0
  • j
    的增量值分配给
    j
    ,即
    j
    现在变为
    1
  • 从步骤1计算出的值0被分配给
    j
    ,因此
    j
    再次变为
    0
  • 使用
    +=
    ,根据:

  • 对左侧进行求值,并生成对变量的引用

  • 然后确定该变量的当前值

  • 对右侧进行评估
    j++
    首先获取
    j
    0
    )的值,然后将其递增。
    j++
    的结果是增量之前的值,即
    0

  • 将结果添加到步骤2中确定的值(
    0
    ),并分配给步骤1中确定的变量(
    j

  • 因此,由于我们每次都将
    0
    分配给
    j
    ,尽管后增量,最终结果是
    0

    以下是规范的实际语言:

    如果左侧操作数表达式不是数组访问表达式,则:

    • 首先,对左侧操作数求值以生成变量。如果此计算突然完成,则赋值表达式也会因为相同的原因突然完成;不计算右侧操作数,也不进行赋值

    • 否则,将保存左侧操作数的值,然后计算右侧操作数的值。如果此计算突然完成,则赋值表达式也会因为相同的原因突然完成,并且不会发生赋值

    • 否则,左侧变量的保存值和右侧操作数的值将用于执行二进制