Java短路混乱
Java short circuit confusion
此代码在 for 循环条件中使用了 &&。它迭代 4 次,得到答案 "sum = 20"。我认为它迭代了 5 次,因为 && 条件的左侧为真,当右侧变为假时结束循环。
基本上我的问题是为什么它迭代了 4 次而不是 5 次,使得 "sum = 30"?谢谢
`int[] lst = {1,2,3,4,5,4,3,2,1};
int sum = 0;
for (int frnt = 0, rear = lst.length - 1;
frnt < 5 && rear >= 5; frnt++, rear--){
sum = sum + lst[frnt] + lst[rear];
System.out.println("frnt: " + frnt);
System.out.println("rear: " + rear);
System.out.println();
}
System.out.print(sum);`
只有当整个表达式的值已知时才会发生短路。
对于逻辑与运算符 (&&),如果左侧已经为假,则右侧的计算结果无关紧要,因为整个表达式已经为假。如果左侧为真,则右侧的值决定表达式的值。既然要评价才知道,所以一定要评价。
对于逻辑或运算符 (||),情况正好相反。如果表达式的左侧为真,那么右侧是什么并不重要,表达式为真,因此不对右侧求值。如果左侧为假,则表达式的值取决于右侧,因此必须对其求值。
问题出在 for
条件下。在循环的最后一次迭代中,frnt = 4
和 rear = 4
。条件 frnt < 5
有效,但 rear >= 5
为假,使整个表达式为假,从而中断循环。请参阅下面的每次迭代后的变量(注意 table 显示每次循环体 运行 并且变量已被修改后的变量)。
frnt rear
before loop: 0 8
iteration 1: 1 7
iteration 2: 2 6
iteration 3: 3 5
iteration 4: 4 4 <---- Loop breaks after this
两个计数器在 4 处在中间相遇,但条件指定 rear >= 5
。为了获得正确的行为,请将条件更改为:frnt < 5 && rear >= 4
,或者更明确地说,frnt <= 4 && rear >= 4
frnt
---- rear
---------- frnt < 5 && rear >= 5
0
------------8
--------------------true && true -> true
1
------------7
--------------------true && true -> true
2
------------6
--------------------true && true -> true
3
------------5
--------------------true && true -> true
4
------------4
--------------------true && false -> false
一切正常,4 次迭代就是这样。
我觉得你误解了短路原理。在 && 运算符的情况下,短路原理如下:
因为A && B操作的结果是true
只有在两个操作数都是true
的情况下,然后在评估操作数A并发现它是false
时,没有需要评估和检查操作数 B 的值。如果操作数 A 为 true
,则始终评估操作数 B。因此,在您的情况下,当循环中断时检查操作数 A 是 4 < 5
,而操作数 B 是 4 >= 5
。因此,由于操作数 A 是 true
,因此必须对操作数 B 进行求值和检查,并且这种情况不是短路,因为两个操作数都被求值了。如果操作数 A 为 false
并且操作数 B 未被评估,则为短路情况。
此代码在 for 循环条件中使用了 &&。它迭代 4 次,得到答案 "sum = 20"。我认为它迭代了 5 次,因为 && 条件的左侧为真,当右侧变为假时结束循环。
基本上我的问题是为什么它迭代了 4 次而不是 5 次,使得 "sum = 30"?谢谢
`int[] lst = {1,2,3,4,5,4,3,2,1};
int sum = 0;
for (int frnt = 0, rear = lst.length - 1;
frnt < 5 && rear >= 5; frnt++, rear--){
sum = sum + lst[frnt] + lst[rear];
System.out.println("frnt: " + frnt);
System.out.println("rear: " + rear);
System.out.println();
}
System.out.print(sum);`
只有当整个表达式的值已知时才会发生短路。
对于逻辑与运算符 (&&),如果左侧已经为假,则右侧的计算结果无关紧要,因为整个表达式已经为假。如果左侧为真,则右侧的值决定表达式的值。既然要评价才知道,所以一定要评价。
对于逻辑或运算符 (||),情况正好相反。如果表达式的左侧为真,那么右侧是什么并不重要,表达式为真,因此不对右侧求值。如果左侧为假,则表达式的值取决于右侧,因此必须对其求值。
问题出在 for
条件下。在循环的最后一次迭代中,frnt = 4
和 rear = 4
。条件 frnt < 5
有效,但 rear >= 5
为假,使整个表达式为假,从而中断循环。请参阅下面的每次迭代后的变量(注意 table 显示每次循环体 运行 并且变量已被修改后的变量)。
frnt rear
before loop: 0 8
iteration 1: 1 7
iteration 2: 2 6
iteration 3: 3 5
iteration 4: 4 4 <---- Loop breaks after this
两个计数器在 4 处在中间相遇,但条件指定 rear >= 5
。为了获得正确的行为,请将条件更改为:frnt < 5 && rear >= 4
,或者更明确地说,frnt <= 4 && rear >= 4
frnt
---- rear
---------- frnt < 5 && rear >= 5
0
------------8
--------------------true && true -> true
1
------------7
--------------------true && true -> true
2
------------6
--------------------true && true -> true
3
------------5
--------------------true && true -> true
4
------------4
--------------------true && false -> false
一切正常,4 次迭代就是这样。
我觉得你误解了短路原理。在 && 运算符的情况下,短路原理如下:
因为A && B操作的结果是true
只有在两个操作数都是true
的情况下,然后在评估操作数A并发现它是false
时,没有需要评估和检查操作数 B 的值。如果操作数 A 为 true
,则始终评估操作数 B。因此,在您的情况下,当循环中断时检查操作数 A 是 4 < 5
,而操作数 B 是 4 >= 5
。因此,由于操作数 A 是 true
,因此必须对操作数 B 进行求值和检查,并且这种情况不是短路,因为两个操作数都被求值了。如果操作数 A 为 false
并且操作数 B 未被评估,则为短路情况。