Java表达式计算优先级:方法调用&;数组索引
在研究java表达式计算顺序的过程中,我遇到了一个我无法向自己解释清楚的现象。有两个问答题。它被要求定义控制台输出 示例1Java表达式计算优先级:方法调用&;数组索引,java,operators,operator-precedence,associativity,Java,Operators,Operator Precedence,Associativity,在研究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 + ",
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 ! ~ ++ -- + - (类型)从右向左铸造新的
3*/%从左到右
4+-从左到右
...
14=+=-=其余部分从右到左省略
通过上表可以清楚地看出,在示例1中,具有最高优先级的运算符是数组索引a[b]
,然后从右到左计算分配运算符:b=0
,然后a[1]=0
。这就是为什么a=[5,0]
但是例子2让我很困惑。根据优先级表,具有最高优先级的操作符是f1(i)
方法调用(应打印0
),然后是一元后增量i++
(使用当前i=0
并在之后递增),然后是加法操作符0+0
和аssignment操作符最后i=0
。因此,我假设正确的输出是0,0
但事实并非如此。事实上,首先计算一元后增量i++
(将i
增加到1
),然后方法调用f1(i)
打印1
,并返回0
,最后由分配运算符赋值i=0+0
,所以最后的i
值是0
,正确答案是1,0
我认为这是由于二进制加法运算符“从左到右”的关联性造成的,但在这种情况下,为什么在示例2中首先计算加法,而在示例1中,首先计算最高优先级的运算符
a[b]
?我注意到示例2中的所有操作符都在不同的组中,所以我们根本不应该考虑操作符的关联性,对吗?难道我们不应该对示例2中的所有运算符按优先级排序并按结果顺序求值吗?运算符的存在相关性和关联性会影响源代码解析为表达式树的方式。但是:任何表达式中的求值顺序仍然是从左到右
这就是为什么在i+++f1(i)
中,我们首先计算i++
,然后计算它们的和
具有最高优先级的方法调用意味着
i+++f1(i)
永远不会被解析为(i+++f1)(i)
(如果这有意义的话),而是始终i++(f1(i))
。优先级并不意味着“先求值后求值”。运算符的存在依赖性和关联性会影响源代码解析到表达式树中的方式。但是:任何表达式中的求值顺序仍然是从左到右
这就是为什么在i+++f1(i)
中,我们首先计算i++
,然后计算它们的和
具有最高优先级的方法调用意味着i+++f1(i)
永远不会被解析为(i+++f1)(i)
(如果这有意义的话),而是始终i++(f1(i))
。优先级并不意味着“比其他任何东西都要先进行评估。”您会感到困惑
=
的从右到左关联性意味着
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
你把我搞糊涂了
=
的从右到左关联性意味着
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
我在这里发布了另一个链接,其中明确描述了评估顺序和优先级的区别(如果其他人需要):我在这里发布了另一个链接,其中明确描述了评估顺序和优先级的区别(如果其他人需要):