我今天偶然写了一些代码,当Eclipse没有对我大喊大叫时,我感到很惊讶。该代码使用了结构相等运算符(==
),类似于下面的if(a==b==c)
结构。
public class tripleEqual {
public static void main(String[] args) {
boolean[] a = { true, false };
boolean[] b = { true, false };
boolean[] c = { true, false };
for (int aDex = 0; aDex < 2; aDex++) {
for (int bDex = 0; bDex < 2; bDex++) {
for (int cDex = 0; cDex < 2; cDex++) {
if (a[aDex] == b[bDex] == c[cDex]) {
System.out.printf("Got a==b==c with %d %d %d\n", aDex, bDex, cDex);
}
}
}
}
}
}
输出
Got a==b==c with 0 0 0
Got a==b==c with 0 1 1
Got a==b==c with 1 0 1
Got a==b==c with 1 1 0
到处玩,我注意到if(a==b==c)
除了boolean
以外的任何类型都不能( A'. B'. C') + ( A'. B . C ) + ( A . B'. C ) + ( A . B . C')
。从那里布尔表达式是
(A=B).'C + (A<>B).C
简化为if(a==b==c)
。
因此,忽略副作用,if(a==b && !c) || (a!=b && c))
等于if(a==b==c)
。
任何人都可以解释( A'. B'. C') + ( A'. B . C ) + ( A . B'. C ) + ( A . B . C')
语法如何表明这一点吗?
修改1:
在很多人解释了左倾相关性之后,我发现了我的困惑。通常我会将'1'表示为true而将'0'表示为false,但是在上面的测试中我的最小化真值表/输出,我的'0'表示真,'1'表示假。表达式(A=B)=C
的否定是{{1}}!
答案 0 :(得分:32)
The ==
operator is left-associative,因此a == b == c
被解释为(a == b) == c
。因此a == b
会返回一个bool,然后将其与c
进行比较。
这是解析器的副作用,在实践中很少有用。正如你所观察到的那样,看起来它只做了一件事但做了一些非常不同的事情(所以即使它做了你想做的事情,也不建议这样做)。有些语言实际上使==
运算符非关联,因此a == b == c
是语法错误。
答案 1 :(得分:9)
到处玩,我注意到如果(a == b == c)除了布尔值以外的任何类型我都做不了。
除boolean
之外,您不能使用任何类型,因为此比较链将从左侧到右侧进行评估。第一次比较将简化为true
或false
值,必须与链中的第三个值进行比较(此检查的结果将与第四个值进行比较,依此类推,直至结束链)。至于原始值,你只能比较相同类型的基元(例如boolean和boolean将起作用,而double和boolean则不起作用) - 这就是为什么你只能用布尔值来做 - 因为==
返回与链中所有值相同类型的值
这里存在危险:当您提供的所有值都是true
时,所有比较链的结果都不等于true
。您可以从第二个输出中看到它:true
== false
== false
会引发true
,如果您从左到右评估它是正确的结果(因为它在程序执行期间发生),但如果您认为必须同时评估此比较链,则可能似乎错误。正确的方法是两次执行两次显式比较:
if (a == b && b == c) {
// do something
}