gpt4 book ai didi

java - Java 中求值顺序的规则是什么?

转载 作者:IT老高 更新时间:2023-10-28 11:41:03 25 4
gpt4 key购买 nike

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

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

文中作者没有给出明确的解释,最后一行的效果是: a[1] = 0;
我不太确定我是否理解:评估是如何进行的?

最佳答案

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

子表达式的求值顺序与结合性和优先级无关 .关联性和优先级决定了运算符的执行顺序,但 不要确定子表达式的计算顺序。您的问题是关于评估子表达式的顺序。

考虑 A() + B() + C() * D() .乘法优先于加法,加法是左结合的,所以这等价于(A() + B()) + (C() * D())但是知道这只会告诉您第一次加法将在第二次加法之前发生,而乘法将在第二次加法之前发生。 它不会告诉您 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() 的左侧,因此首先计算 A(),而不管 C() 涉及乘法而 A() 仅涉及加法这一事实。

所以现在你有足够的信息来回答你的问题。在 a[b] = b = 0结合律说这是 a[b] = (b = 0);但这并不意味着 b=0先跑!优先级规则说索引的优先级高于赋值,但 这并不意味着索引器在最右边的赋值之前运行 .

(更新:此答案的早期版本在接下来的部分中有一些小且实际上不重要的遗漏,我已更正。我还写了一篇博客文章,描述了为什么这些规则在 Java 和 C# 中是合理的: https://ericlippert.com/2019/01/18/indexer-error-cases/)

优先级和结合性仅告诉我们将零赋值给 b必须在分配给 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]最后发生。

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

    人们总是把这些东西弄错了,即使是那些应该知道得更好的人。我编辑了太多错误说明规则的编程书籍,所以很多人对优先级/结合性和评估顺序之间的关系有完全错误的信念也就不足为奇了——也就是说,实际上没有这种关系;他们是独立的。

    如果您对这个主题感兴趣,请参阅我关于该主题的文章以进一步阅读:

    http://blogs.msdn.com/b/ericlippert/archive/tags/precedence/

    它们是关于 C# 的,但其中大部分内容同样适用于 Java。

    关于java - Java 中求值顺序的规则是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6800590/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com