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

时间:2015-06-17 10:01:46

标签: 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++;
            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

6 个答案:

答案 0 :(得分:6)

因为,j++表示评估后的增量,而j+=x表示j=j+x,因此j在评估j+1之后变为j=j+j在计算此加法后,该值为零(加法结果为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,所以它会永远保持这种状态,并在每次循环运行中在很短的时间内闪烁一次。

在评估j += j++;期间,也许你可以使j变为volatile,然后由其他线程在循环中读取它。阅读线程可能会看到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
...

在我的机器上,为了评估j += j++

,我很高兴看到中间人1的运气好转

答案 1 :(得分:4)

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

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

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

  1. 您阅读的是j = 0
  2. 您再次阅读j = 0
  3. 您计算j = j + 1
  4. 但是,现在您计算j = 0 + 0并覆盖该值
  5. 因此,在迭代结束时,j的值没有改变。它仍然是0.对于每次迭代都是如此,这就是为什么j的值永远不会改变的原因。

答案 2 :(得分:3)

问题出现是因为&#39; j ++&#39;如果在语句中使用,则以下列格式工作 -

  1. 首先在语句
  2. 中使用j的值
  3. 然后j的值增加。
  4. 在您的情况下,当您执行j += j++时会发生什么 -

    1. 首先在语句中使用j的值,在语句中使用,因此j++返回0以在语句中使用,并且我们计算了{{1} }}被分配到0 + 0(尚未分配)。
    2. j的递增值已分配给j,现在j变为j
    3. 从步骤1计算的值(0)被分配给1,因此j再次变为j

答案 3 :(得分:2)

  

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

现在j += j++;

j添加到0时,j0 += 0。因此0将是j

  

价值被过度使用,因此0永远保持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

现在尝试使用预增量。

j + = ++ j;

输出:

table.chess_board  tr.chess_line {
  background-color: blue;
 }

有道理吗?

答案 4 :(得分:1)

+=JLS§15.26.2

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

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

  3. 评估右手方面。 j++首先获取j0)的值,然后递增它。 j++的结果是增量之前的值0

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

  5. 因为我们每次最终都会将0分配给j,尽管有后期增量,但最终结果为0

    这是规范的实际语言:

      

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

         
        
    • 首先,评估左侧操作数以生成变量。如果此评估突然完成,则赋值表达式出于同样的原因突然完成;不评估右侧操作数,也不进行赋值。

    •   
    • 否则,保存左侧操作数的值,然后计算右侧操作数。如果此评估突然完成,则赋值表达式会因同样的原因而突然完成,并且不会发生任何分配。

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

    •   
    • 否则,二进制运算的结果将转换为左侧变量的类型,经过值集转换(第5.113节)到相应的标准值集(不是扩展指数值) set),转换结果存储在变量中。

    •   

答案 5 :(得分:0)

问题出在这里

j += j++;

在开头j = 0,然后j++表示j将在下一次迭代中递增。但是,在下一次迭代之前,您将0分配到j。 因此j重新分配给0