j += j++ 在 Java 中做什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30888331/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:47:20  来源:igfitidea点击:

What does j += j++ do in Java?

java

提问by Zeta.Investigator

Can anyone explain this behavior to me?
First, I thought the answer would be 511 + 512 (if j += j++ would mean j = j + (j+1))
How can I justify the answer zero?

谁能向我解释这种行为?
首先,我认为答案是 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

采纳答案by Ori Lentz

Because when you do a = b + cyou first read band cand then calculate the values.

因为当你做a = b + c你先阅读bc再计算值。

Also, j++means returns the current value of j and then increment it by one.

此外,j++means 返回 j 的当前值,然后将其加一。

In your case, since you do j = j + j++you first read j, then you read jagain and returns the value of j. Let's do an example with the first iteration:

在您的情况下,由于您j = j + j++首先阅读j,然后j再次阅读并返回 的值j。让我们用第一次迭代做一个例子:

  1. You read j = 0
  2. You read j = 0 again
  3. You compute j = j + 1
  4. However, now you compute j = 0 + 0and override that value
  1. 你读 j = 0
  2. 你又读了 j = 0
  3. 你计算 j = j + 1
  4. 但是,现在您计算j = 0 + 0并覆盖该值

So by the end of the iteration, j's value hasn't changed. It's still 0. That's true for every iteration which is why the value of jnever changes.

所以在迭代结束时,j的值没有改变。它仍然是 0。对于每次迭代都是如此,这就是为什么值j从不改变的原因。

回答by Krzysztof Cichocki

Because, the j++, means increment after evaluation, and j+=xmeans j=j+xso the jbecomes j+1after evaluating j=j+jwhich is zero( the addition result is 0) after computation of this addition, the j is incremented by j++, but after that the addition result overrides the incremented j value by its value 0.

因为,j++,手段评估后递增,和j+=x装置j=j+x因此j变得j+1评估后j=j+j它是一个零(相加的结果是0)这个另外的计算之后,第j设为j ++递增,但在这之后的相加结果重写递增Ĵ值以其值为 0。

look at this, let assume j=0;

看看这个,假设 j=0;

j += j++

the j++incrementation will be executed after reading the jvalue, which is 0for now.

j++增量将阅读后执行j价值,这是0现在。

so it translates into:

所以它转化为:

   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

So the j becomes a 1 for a very short time in this case, but is overridden very quickly after that.

因此,在这种情况下, j 在很短的时间内变为 1,但之后很快就会被覆盖。

The conclusion is that mathematically j += j++;finally becomes only j = j + j;

结论是数学上j += j++;最终变成只有j = j + j;

in your for loop this situation repeats every single loop execution, initially the j is 0, so it stays like that forever with blinking to one for a very short time in each loop run.

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

Maybe you could make the j volatile and then read it in a loop by other thread during evaluation of this j += j++;. The reading thread could probably see that j becomes 1 for a moment, but this is indeterministic, in my case I see this happening using this simple test program:

也许您可以使 j 变得易变,然后在评估 this 期间由其他线程在循环中读取它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++;
        }

    }

}

the output is:

输出是:

...
0
0
0
1
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
0
0
0
...

On my machine it seems to happpen pretty often to have the luck of reading the intermediate 1 for the evaluation of j += j++

在我的机器上,似乎经常有幸阅读中间 1 来评估 j += j++

回答by Anand S Kumar

The issue occurs because 'j++' which if used inside a statement works in the following format -

出现此问题是因为“j++”如果在语句中使用,则按以下格式工作 -

  1. First the value of jis used inside the statement
  2. Then the value of jis increased.
  1. 首先j在语句中使用的值
  2. 然后 的值j增加。

In your case, when you do j += j++what happens is -

在你的情况下,当你做的j += j++事情是 -

  1. First the value of jis used inside the statement , is used in the statement, hence j++returns 0to be used in the statement, and we have computed 0 + 0to be assigned to j(not yet assigned) .
  2. The incremented value of jis assigned to j, that is jnow becomes 1.
  3. The value computed from Step 1 , which is 0 is assigned to j, hence jbecomes 0again.
  1. 首先在j语句中使用的值 ,在语句中使用,因此j++返回0以在语句中使用,并且我们已经计算出0 + 0要分配给j(尚未分配)。
  2. 的递增值j分配给j,即j现在变为1
  3. 从步骤 1 计算的值,即 0 被分配给j,因此再次j变为0

回答by Uma Kanth

What does a post-increment operator do? Increment after the operation is completed.

后增量运算符有什么作用?操作完成后递增。

Now j += j++;

现在 j += j++;

Here jis 0when it is added to j. so 0 += 0will be a 0.

j0添加到j. 所以0 += 0将是一个0.

The value is over-rided so jstays 0forever.

该值过rided所以j住宿0永远。

Let's try with the pre-increment now.

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

j += ++j;

j += ++j;

Output:

输出:

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

makes sense?

说得通?

回答by T.J. Crowder

With +=, per JLS§15.26.2:

随着+=JLS§15.26.2

  1. The left-hand side is evaluated and produces a reference to a variable.

  2. The then-current value of that variable is determined.

  3. The right handside is evaluated. j++first gets the value of j(0), then increments it. The result of j++is the value beforethe increment, which is 0.

  4. The result is added to the value determined in Step 2 (0) and assigned to the variable determined in Step 1 (j).

  1. 评估左侧并生成对变量的引用。

  2. 确定该变量的当时值。

  3. 右手侧进行评估。j++首先获取j( 0)的值,然后将其递增。的结果j++是增量的值,即0

  4. 结果与步骤 2 ( 0) 中确定的值相加,并分配给步骤 1 ( j) 中确定的变量。

So since we end up assigning 0to jevery time, despite the post-increment, the ultimate result is 0.

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

Here's the spec's actual language:

这是规范的实际语言:

If the left-hand operand expression is not an array access expression, then:

  • First, the left-hand operand is evaluated to produce a variable. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason; the right-hand operand is not evaluated and no assignment occurs.

  • Otherwise, the value of the left-hand operand is saved and then the right-hand operand is evaluated. If this evaluation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.

  • Otherwise, the saved value of the left-hand variable and the value of the right-hand operand are used to perform the binary operation indicated by the compound assignment operator. If this operation completes abruptly, then the assignment expression completes abruptly for the same reason and no assignment occurs.

  • Otherwise, the result of the binary operation is converted to the type of the left-hand variable, subjected to value set conversion (§5.1.13) to the appropriate standard value set (not an extended-exponent value set), and the result of the conversion is stored into the variable.

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

  • 首先,评估左边的操作数以产生一个变量。如果这个评估突然完成,那么赋值表达式也会因为同样的原因突然完成;不计算右侧操作数,也不进行赋值。

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

  • 否则,左侧变量的保存值和右侧操作数的值用于执行复合赋值运算符指示的二元运算。如果此操作突然完成,则赋值表达式出于同样的原因突然完成并且不会发生赋值。

  • 否则,二元运算的结果将转换为左侧变量的类型,经过值集转换(第 5.1.13 节)到适当的标准值集(不是扩展指数值集),结果转换的结果存储到变量中。

回答by rakeb.mazharul

The problem is here

问题就在这里

j += j++;

At the begining, j = 0, then j++means jwill increment in the next iteration. But, before the next iteration, you are assigning the 0into j. So jre assigned to 0.

开始时,j = 0, 则j++表示j将在下一次迭代中递增。但是,在下一次迭代之前,您将分配0into j。所以j重新分配给0.