【发布时间】: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