Java,“a [1] * = a [1] = b [n + 1]”无法按预期工作?

时间:2018-03-21 06:13:41

标签: java variable-assignment multiplication assignment-operator

正如标题所示,我有一个使用临时数组的函数,我想从另一个数组中写入一个值,然后将这两个值与它们相乘。

示例:

float[] a = {0, 0}

a[0] *= a[0] = b[n    ];
a[1] *= a[1] = b[n + 1];

我希望上面会做到以下几点:

a[0] = b[n    ];
a[0] *= a[0]; //(aka: a[0] = a[0] * a[0])

a[1] = b[n + 1];
a[1] *= a[1];

虽然这种行为似乎没有发生。相反,它似乎只是乘以“a”中的原始值与“b”中保存的任何值相乘:

a[0] = a[0] * b[n    ];
a[1] = a[1] * b[n + 1];

总是我的理解是,首先评估“=”之后的任何内容,如下所示:

float a, b;
a = b = 5;
//"a" and "b" both equal "5" now.

就是这样,是不是表明我原来的例子应该有效?

任何人都可以解释发生了什么以及为什么此代码无法正常工作?

4 个答案:

答案 0 :(得分:7)

我认为到目前为止的答案并不正确。最重要的是评估像a *= b这样的复合表达式。简而言之,左侧的值在右侧之前计算。来自JLS(强调我的):

  

在运行时,表达式以两种方式之一进行评估。

     

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

     

首先,评估左侧操作数以生成变量。如果   此评估突然完成,然后是赋值表达式   因同样的原因突然完成;右手操作数不是   评估并且没有分配。

     

否则,保存左侧操作数的值,然后保存   评估右侧操作数。如果此评估完成   然后突然完成赋值表达式   同样的原因,没有任何转让。

     

否则,保存左侧变量的值和值   右侧操作数用于执行二进制操作   由复合赋值运算符表示。如果这个操作   突然完成,然后赋值表达式突然完成   出于同样的原因,没有任何转让。

     

否则,二进制操作的结果将转换为该类型   左侧变量的值,经过值集转换(§5.1.13)   到适当的标准值集(不是扩展指数值)   set),转换结果存储在变量中。

在你的例子中:

a[0] *= a[0] = b[n    ];
  1. 计算a[0]的值,并将其存储在tmp
  2. 中 评估
  3. a[0] = b[n],给出b[n]的值(并将a[0]的值更改为b[n]
  4. 计算
  5. tmp * a[0]
  6. 将最后一步的结果分配给a[0]
  7. 所以,你得到的是a[0] *= b[n]

    编辑:关于从右到左 - 评估分配的混淆:我没有找到JLS中使用的术语,恕我直言,这是不正确的(尽管它在Java教程中使用)。它被称为正确 - ** associative * assThe JLS说这是关于任务的:

      

    有12个赋值运算符;一切都是语法上的   右联想(他们从右到左分组)。因此,a = b = c表示   a =(b = c),它将c的值赋给b,然后赋值   b到a。

答案 1 :(得分:3)

参考Java documentation

  

除了赋值运算符之外的所有二元运算符都是从左到右计算的;赋值运算符从右到左进行求值。

因此,a[0] *= a[0] = b[n ];的情况是,您为a[0]分配b[n]的值,然后将原始a[0]乘以该新值。所以你的表达有效a[0] *= b[n]

就个人而言,我不会在一行上使用赋值运算符两次,这可能会令人困惑。

答案 2 :(得分:2)

分配运算符(与大多数其他运算符不同)在Java(documentation)中从进行评估。这意味着以下内容:

a[0] *= a[0] = b[n];

实际上被评估为:

a[0] *= (a[0] = b[n]);

括号中的数量是一项赋值,并返回值b[n],但不会更改a[0]的值。然后,进行以下最终分配:

a[0] = a[0] * b[n]

*==都是赋值运算符,并且具有相同的优先级。因此,在这种情况下,适用从右到左的规则。

答案 3 :(得分:0)

答案中似乎没有指出的关键点是*=不仅仅是一个赋值运算符,而是一个复合赋值运算符。 / p>

The language spec表示以下内容相同:

E1 op= E2
    <=>
E1 = (T) ((E1) op (E2))

其中op=类似于*=+=等。

因此:

a[0] *= a[0] = b[n    ];

相当于:

a[0] = a[0] * (a[0] = b[n]);
由于left-to-right evaluation order

a[0](a[0] = b[n])之前进行了评估。

所以:

  • 这会从a[0]读取值(称之为“A”)
  • 它从b[n]读取值(称之为“B”)
  • 它将B分配给a[0](*)
  • 然后乘以A * B(称之为“C”)
  • 然后将C存储回a[0]

所以是的,这相当于将a[0]中的任何内容乘以b[n],因为上面标记为(*)的步骤是多余的:在重新分配之前,永远不会读取分配给它的值。 / p>