Java中评估顺序的规则是什么?

时间:2011-07-23 13:11:07

标签: java operator-precedence

我正在阅读一些Java文本并获得以下代码:

int[] a = {4,4};
int b = 1;
a[b] = b = 0;

在文中,作者没有给出明确的解释,最后一行的效果是:a[1] = 0;

我不太清楚我理解:评估是如何发生的?

5 个答案:

答案 0 :(得分:166)

答案 1 :(得分:33)

Eric Lippert的精湛答案虽然不是很有帮助,因为它正在谈论另一种语言。这是Java,其中Java语言规范是语义的权威描述。特别是,§15.26.1是相关的,因为它描述了=运算符的评估顺序(我们都知道它是右关联的,是吗?)。在这个问题中将它减少到我们关心的位:

  

如果左侧操作数表达式是数组访问表达式(§15.13),则需要执行许多步骤:

     
      
  • 首先,评估左侧操作数数组访问表达式的数组引用子表达式。如果此评估突然完成,则赋值表达式出于同样的原因突然完成;索引子表达式(左侧操作数数组访问表达式)和右侧操作数未被评估,也不会发生任何赋值。
  •   
  • 否则,将评估左侧操作数数组访问表达式的索引子表达式。如果此评估突然完成,则赋值表达式会出于同样的原因突然完成,并且不会评估右侧操作数并且不会发生任何赋值。
  •   
  • 否则,将评估右侧操作数。如果此评估突然完成,则赋值表达式会因同样的原因而突然完成,并且不会发生任何分配。
  •   

[...然后继续描述赋值本身的实际含义,为简洁起见,我们可以忽略这一点......]

简而言之,Java有一个非常严格定义的evaluation order,它在任何运算符或方法调用的参数中几乎都是从左到右。数组赋值是更复杂的情况之一,但即便如此,它仍然是L2R。 (JLS确实建议您不要编写需要这些复杂语义约束的代码,我也是如此:每个语句只需要一个赋值,就会遇到很多麻烦!)< / p>

C和C ++在这方面肯定与Java不同:它们的语言定义会故意定义评估顺序以实现更多优化。 C#显然与Java类似,但我不能很好地了解它的文献,无法指出正式的定义。 (这确实因语言而异,Ruby严格来说是L2R,就像Tcl一样 - 虽然缺少一个赋值运算符本身,原因与这里不相关 - 而Python是L2R but R2L in respect of assignment,我发现奇怪,但你去。)

答案 2 :(得分:5)

a[b] = b = 0;

1)数组索引运算符的优先级高于赋值运算符(参见this answer):

(a[b]) = b = 0;

2)根据15.26。 JLS

的分配运算符
  

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

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

3)根据15.7。评估顺序JLS

  

Java编程语言保证运算符的操作数似乎以特定的评估顺序进行评估,即从左到右。

  

在评估右侧操作数的任何部分之前,二元运算符的左侧操作数似乎已完全评估。

所以:

a)(a[b])首先评估为a[1]

b)然后(b=0)评估为0

c)(a[1] = 0)最后评估

答案 3 :(得分:1)

您的代码相当于:

int[] a = {4,4};
int b = 1;
c = b;
b = 0;
a[c] = b;

解释了结果。

答案 4 :(得分:-1)

考虑下面另一个更深入的例子。

作为一般经验法则:

最好在解决这些问题时提供一份“优先顺序规则和关联性”表格,例如: http://introcs.cs.princeton.edu/java/11precedence/

这是一个很好的例子:

System.out.println(3+100/10*2-13);

问题:上述线路的输出是什么?

答案:应用优先权和相关性规则

步骤1:根据优先规则:/和*运算符优先于+ - 运算符。因此,执行此等式的起点将缩小为:

100/10*2

步骤2:根据规则和优先级:/和*优先级相等。

由于/和*运算符的优先级相同,我们需要查看这些运算符之间的关联性。

根据这两个特定运营商的ASSOCIATIVITY RULES, 我们从LEFT TO RIGHT开始执行等式,即首先执行100/10:

100/10*2
=100/10
=10*2
=20

步骤3:等式现在处于以下执行状态:

=3+20-13

根据规则和优先顺序:+和 - 优先级相等。

我们现在需要查看运算符+和 - 运算符之间的关联性。根据这两个特定运营商的相关性, 我们开始执行从LEFT到RIGHT的等式,即首先执行3 + 20:

=3+20
=23
=23-13
=10
编译时

10是正确的输出

同样,在解决这些问题时,重要的是要有一张优先顺序规则和相关性表格,例如: http://introcs.cs.princeton.edu/java/11precedence/