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

时间:2013-11-19 17:33:26

标签: java

我今天偶然写了一些代码,当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}}!

2 个答案:

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

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