双结构相等运算符:if(a == b == c)

我今天偶然写了一些代码,当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 + (AB).C

因此,忽略副作用, if(a==b==c)等于if(a==b && !c) || (a!=b && c)) if(a==b && !c) || (a!=b && c))

任何人都可以解释if(a==b==c)语法如何表明?

编辑1:

很多人解释了左倾相关性后,我发现我的困惑在哪里。 通常我会将’1’表示为true而将’0’表示为false,但是在上面的测试中我的最小化真值表/输出,我的’0’表示真,’1’表示假。 表达式( A'. B'. C') + ( A'. B . C ) + ( A . B'. C ) + ( A . B . C') A’。B’。C ( A'. B'. C') + ( A'. B . C ) + ( A . B'. C ) + ( A . B . C')的否定是(A=B)=C

到处玩,我注意到如果(a == b == c)除了布尔值之外的任何类型我都做不到。

你不能使用任何类型但boolean因为这个比较链将从左侧到右侧进行评估。 第一次比较将简化为true值或false值,必须与链中的第三个值进行比较(此检查的结果将与第四个值进行比较,依此类推,直到链的末尾)。 至于原始值,你只能比较相同类型的基元(例如boolean和boolean将起作用,而double和boolean不会) – 这就是为什么你只能用布尔值来做 – 因为==返回值与链中的所有值相同的类型。
这里存在危险:当您提供的所有值都为true时,所有比较链的结果都不等于true 。 您可以从第二个输出中看到它: true == false == false引发true ,如果您从左到右评估它(正如在程序执行期间发生的那样),这是正确的结果,但如果您认为这可能看起来是错误的比较链必须一次性评估。 正确的方法是执行两次显式比较:

 if (a == b && b == c) { // do something } 

==运算符是左关联的 ,因此a == b == c被解释为(a == b) == c 。 所以a == b返回一个bool,然后将其与c进行比较。

这是解析器的副作用,在实践中很少有用。 正如你所观察到的那样,看起来它做了一件事,但做了一些非常不同的事情(所以即使它做你想做的事情,也不建议这样做)。 有些语言实际上使==运算符非关联,因此a == b == c是语法错误。