【问题标题】:Java expressions calculation precedence: method invocation & array indexingJava表达式计算优先级:方法调用&数组索引
【发布时间】:2020-07-05 10:56:32
【问题描述】:

在学习java表达式计算顺序的过程中,我遇到了一个我无法解释清楚的现象。有两个测验问题。它被要求定义控制台输出。

示例 1

int[] a = {5, 5};
int b = 1;
a[b] = b = 0;
System.out.println(Arrays.toString(a));

正确的控制台输出是:[5,0]

示例 2

public class MainClass {

    static int f1(int i) {
        System.out.print(i + ",");
        return 0;
    }

    public static void main(String[] args) {
        int i = 0;
        i = i++ + f1(i);
        System.out.print(i);
    }
}

正确的控制台输出是:1,0

据我所知,Java 中存在具有有序优先级的运算符组(级别),表达式根据运算符优先级进行评估。每个组也存在关联性,如果运算符具有相同的优先级,则按照组关联性指定的顺序对它们进行评估。运算符优先级表(来自 Cay S. Horstmann - Core Java V.1):

# 运算符 关联性 1 [] 。 () 方法调用从左到右 2! ~ ++ -- + - (type) cast new 从右到左 3 * / % 从左到右 4 + - 从左到右 ... 14 = += -= 其余省略 从右到左

通过上表可以清楚地看出,在示例 1 中,具有最高优先级的运算符是数组索引a[b],然后赋值运算符从右到左计算:b=0,然后是a[1]=0。这就是为什么a=[5,0]

但是示例 2 让我感到困惑。根据优先级表,优先级最高的运算符是f1(i)方法调用(应该打印0),然后是一元后增量i++(使用当前i=0并递增之后),然后是加法运算符0+0,最后是赋值运算符i=0。所以,我认为正确的输出是0,0

但事实上并非如此。实际上,首先计算一元后增量i++i 增加到1),然后方法调用f1(i) 打印1 并返回0,最后是赋值运算符分配i=0+0,因此最终的i 值为0,正确答案为1,0

我想这是由于二进制加法运算符关联性“从左到右”,但在这种情况下,为什么在示例 2 中首先计算加法,但在示例 1 中首先计算最高优先级运算符 a[b]?我注意到示例 2 中的所有运算符都在不同的组中,所以我们根本不应该考虑运算符的关联性,不是吗?我们不应该按优先级对示例 2 中的所有运算符进行排序并按结果顺序对其进行评估吗?

【问题讨论】:

    标签: java operators operator-precedence associativity


    【解决方案1】:

    运算符的存在性和关联性会影响将源代码解析为表达式树的方式。但是:任何表达式中的求值顺序仍然是从左到右的。

    这就是为什么在i++ + f1(i) 中,我们首先评估i++,然后是f1(i),然后计算它们的总和。

    具有最高优先级的方法调用意味着i++ + f1(i) 永远不会被解析为(i++ + f1)(i)(如果这有意义的话),但总是i++ + (f1(i))。优先级并不意味着“在其他任何事情之前进行评估。”

    【讨论】:

      【解决方案2】:

      您将evaluation orderprecedence 混淆了。

      = 的从右到左的关联性意味着

      a[b] = b = 0;
      

      被评估为

      a[b] = (b = 0);
      

      但评估仍然是从左到右,所以第一个b 的值在b 的值更新之前评估

      a[b] = (b = 0)     a = { 5, 5 }, b = 1
      // evaluate 'b'
      a[1] = (b = 0)     a = { 5, 5 }, b = 1
      // evaluate 'b = 0'
      a[1] = 0           a = { 5, 5 }, b = 0
      // evaluate 'a[1] = 0'
      0                  a = { 5, 0 }, b = 0
      

      【讨论】:

      猜你喜欢
      • 2020-06-23
      • 2014-08-02
      • 2017-12-25
      • 1970-01-01
      • 2011-07-24
      • 2021-10-04
      • 1970-01-01
      • 2013-08-04
      • 2020-08-19
      相关资源
      最近更新 更多