当前位置: 首页 > 面试题库 >

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

子车灿
2023-03-14
问题内容

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

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

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

我不确定自己是否理解:评估是如何发生的?


问题答案:

让我说得很清楚,因为人们一直误会这一点:

子表达式的求值顺序与关联性和优先级无关。结合性和优先级确定以什么顺序运营商执行,但不以什么顺序确定的子表达式进行评估。你的问题与子表达式的计算顺序有关。

考虑一下A() + B() + C() * D()。乘法比加法具有更高的优先级,并且加法是左关联的,所以这等效于(A() + B()) + (C() * D()) But。但是,知道这仅告诉你第一次加法将在第二次加法之前发生,并且乘法将在第二次加法之前发生。它不会告诉你将以什么顺序调用A(),B(),C()和D()!(它也不会告诉你的乘法运算是之前还是先添加后发生的。)这将是完全有可能遵守规则的优先级和结合通过编写此为:

d = D()          // these four computations can happen in any order
b = B()
c = C()
a = A()
sum = a + b      // these two computations can happen in any order
product = c * d
result = sum + product // this has to happen last

在那里遵循所有优先级和关联性规则-第一个加法发生在第二个加法之前,而乘法发生在第二个加法之前。显然,我们可以以任何顺序调用A(),B(),C()和D(),并且仍然遵守优先级和关联性规则!

我们需要一个与优先级和关联性规则无关的规则,以解释子表达式的求值顺序。Java(和C#)中的相关规则是“子表达式从左到右求值”。由于A()出现在C()的左侧,因此无论C()参与乘法而A()仅涉及加法,都首先评估A()。

因此,现在你有足够的信息来回答你的问题。在a[b] = b = 0关联性规则中说这是a[b] = (b = 0);事实,但这并不意味着b=0先行!优先规则说索引比分配优先级更高,但这并不意味着索引器在最右边的分配之前运行。

(更新:此答案的较早版本在随后的部分中进行了一些小的且实际上不重要的遗漏,而我已对其进行了更正。我还在此撰写了一篇博客文章,描述了为什么这些规则在Java和C#中是明智的:https:// ericlippert.com/2019/01/18/indexer-error-cases/)

优先级和关联性仅告诉我们,to 的赋值b必须在 to的赋值之前发生a[b],因为零赋值会计算在索引操作中分配的值。优先级和是否关联性单独甭a[b]评估之前或之后的b=0。

同样,这与以下内容相同:A()[B()] = C()-我们所知道的是,索引必须在分配之前进行。我们不知道A(),B()或C()是基于优先级和关联性首先运行的。我们需要另一条规则来告诉我们。

规则再次是,“当你选择要做什么时,请始终从左到右”。但是,在这种特定情况下会有一个有趣的皱纹。由空集合或超出范围的索引引起的引发异常的副作用是否被视为分配左侧计算的一部分,还是分配本身计算的一部分?Java选择后者。(当然,这是一个区别,仅在代码已经错误的情况下才有意义,因为正确的代码不会取消引用null或首先传递错误的索引。)

那会怎样呢?

  • a[b]是的左侧b=0,所以a[b]跑第一,从而导致a[1]。但是,延迟检查此索引操作的有效性。
  • 然后b=0发生。
  • 然后发生a有效且a[1]在范围内的验证
  • a[1]最后要进行的值分配。

因此,尽管在这种特定情况下,对于那些本来不应该在正确的代码中发生的罕见错误情况,仍需要考虑一些细微之处,但是通常你可以推理:左边的事情先于右边的事情发生。这就是你要寻找的规则。关于优先权和关联性的讨论既令人困惑又无关紧要。

人们得到这个东西错了所有的时间,即使是人谁应该更清楚。我编辑了太多编程书籍,错误地陈述了规则,因此不足为奇的是,许多人对优先级/关联性和评估顺序之间的关系抱有完全错误的信念,也就是说,实际上没有这种关系; 他们是独立的。



 类似资料:
  • 问题内容: 假设我有以下表达式 Eclipse警告我,布尔表达式的第二个短语中可能为空。但是,我知道有些人会在第一个条件失败的情况下完全退出布尔表达式。Java是否正确?还是不能保证评估顺序? 问题答案: 但是,我知道有些人会在第一个条件失败的情况下完全退出布尔表达式。Java是否正确? 是的,这就是所谓的短路评估。操作员喜欢和是执行此类操作的操作员。 还是不能保证评估顺序? 不,可以保证评估的顺

  • 问题内容: 我有以下查询: 我有以下问题: USING语法与ON语法同义吗? 这些联接是从左到右评估的吗?换句话说,此查询是否说:x =公司加入了用户;y = x JOIN工作;z = y加入用户帐户; 如果对问题2的回答为“是”,那么可以安全地假设“公司”表中包含“公司ID”,“用户ID”和“工作ID”列? 我不明白在引用别名“ j”时,如何使用WHERE子句来选择公司表上的行 任何帮助,将不胜

  • 问题内容: 有人可以解释一下SELECT语句的概念执行顺序是什么,请提供一个示例吗? 我在Google上进行了搜索,但它们似乎都使用了相同的示例,而没有详尽的解释。 问题答案: 从概念上讲,按以下顺序评估查询: 该条款 该条款 该条款 该条款 该条款 该条款 这是“概念性”处理,解释了SQL的一些作用域规则。实际上,查询的执行方式可能有所不同。 SQL Server文档在此处说明了此顺序。

  • 我理解经典例子的问题 但我无法说服自己以下是有效的还是无效的 我知道'foo(i)'和'i'的求值顺序是不确定的,但是'评估'到底是什么意思?也就是说bar的第二个参数总是42,或者'i'的当前值可以在foo改变它之前被传入吗?

  • 是OCaml内置的函数。 经验: 我的问题:的求值顺序是什么? 是先将求值为8,然后将求值为11?还是先将求值为函数,然后将用作函数的参数? 谢谢

  • 问题内容: 如果您有一个if语句,其中对多个变量或函数进行了评估,那么按什么顺序对其进行评估? 在这种特定情况下,是将foo相对于5评估,然后将6相对于吧(从左至右)进行评估,还是将其从右至左进行评估?我假设a和以相同顺序求值。 问题答案: 如果第一个是,则将首先评估left子句,然后评估第一个。 这就是为什么您可以执行以下操作的原因: 没有破坏。 相反,对于子句,只有第一个为:时,将评估righ