在Java中,布尔运算的“操作顺序”是什么?

74

让我们以一个简单的对象Cat为例。我想确保“非空”的cat是橙色或灰色。

if(cat != null && cat.getColor() == "orange" || cat.getColor() == "grey") {
//do stuff
}

我认为AND优先于OR。但是我有点糊涂了,所以这里是我的问题:

  1. 有人能为我详细解释一下这个语句吗,这样我就能确定它的作用了吗?

  2. 如果我添加括号会发生什么?这会改变运算顺序吗?

  3. 不同编程语言中,我的操作顺序会改变吗?


12
如果你有任何模糊的地方,就加上括号,这样就很明显了。 - Anon.
42
即使您觉得不需要加括号,也请添加括号以便其他人也能理解。 - Brendan Long
3
在布尔逻辑中存在歧义的情况下,可以使用括号来澄清操作顺序。如常规操作一样,在最内层的括号中执行操作,然后是外部的括号,以此类推,直到完成所有括号内的操作。然后执行任何在括号外的操作。 - Stephano
1
可能是StackOverFlow上的许多恶意用户之一。别担心,我认为你的回答也很好。 - davidahines
3
你最好使用cat.getColor().equals("orange")而不是'=='。 - Albert Hendriks
6个回答

75

Java教程提供了一份列出操作符优先级的清单。等式操作符首先被求值,然后是&&,再然后是||。括号将会在任何其他操作之前被求值,因此添加括号可以改变计算顺序。这通常在编程语言之间非常相似,但是最好进行双重检查。

正是你没想到的行为中的小变化可能导致你花费一整天来调试,所以最好放置括号以确保你知道求值顺序。


1
@VinceEmigh 操作数的计算顺序不必与运算符优先级相同。即使添加括号,程序仍然可以看到 if(true || (true && s.equals(""))) 总是为 true,因此根本不需要评估 s.equals("") - Bill the Lizard
我的错,我刚才意识到我非常错误了。我没有正确考虑优先级的问题。我是在思考评估方面(哪个先被评估),就像哪个运算符“拥有”布尔值一样。 - Dioxin

26

布尔运算优先级(适用于所有编程语言):

  1. 括号
  2. 非(NOT)
  3. 与(AND)
  4. 或(OR)

因此,您上面的逻辑等价于:

(cat != null && cat.getColor() == "orange") || cat.getColor() == "grey"

8
表达式基本上与以下内容相同:
if ( (cat != null && cat.getColor() == "orange") || cat.getColor() == "grey") {
  ...
}

这里的优先顺序是AND (&&) 的优先级高于OR (||)。

你还应该知道,在Java中使用==来测试字符串相等性有时会起作用,但这不是正确的做法。你应该这样做:

if (cat != null && ("orange".equals(cat.getColor()) || "grey".equals(cat.getColor()))) {
  ...
}

在IT技术中,对于 String 类型的比较,应使用 equals() 方法而不是简单的引用相等 ==。因为对于字符串的引用相等往往具有误导性。例如:

String a = new String("hello");
String b = new String("hello");
System.out.println(a == b); // false

我觉得你在第一个例子中漏了一个括号,或者是我太累了。 - Robert P

6

首先,您的if语句包含三个主要表达式:

  1. cat != null
  2. cat.getColor() == "orange"
  3. cat.getColor() == "grey"

第一个表达式仅检查cat是否不为null。如果不这样做,第二个表达式将被执行并导致NPE(空指针异常)。这就是为什么在第一个和第二个表达式之间使用&&的原因。当您使用&&时,如果第一个表达式评估为false,则永远不会执行第二个表达式。 最后,您检查猫的颜色是否为灰色。

最后请注意,您的if语句仍然有误,因为如果cat为null,则仍将执行第三个表达式,因此会出现空指针异常

正确的方法是:

if(cat != null && (cat.getColor() == "orange" || cat.getColor() == "grey")) { 
//do stuff 
} 

检查括号的顺序。


5

是的,&&肯定在||之前进行评估。但我看到你正在做cat.getColor() == "orange",这可能会给您带来意外的结果。您可以尝试这样做:

if(cat != null && ("orange".equals(cat.getColor()) || "grey".equals(cat.getColor()))) {
    //do stuff
}

-4
运算顺序并不是你需要的,你需要布尔代数,其中包括布尔函数、极大项/极小项、格雷码、卡诺图、二极管、晶体管、逻辑门、复用器、比特加法器、触发器......你想要的是在计算机或虚拟机上实现布尔“逻辑”。通过“运算顺序”,你可能会提到物理方面的东西,例如在逻辑门(OR、IF)纳秒间隔上管理延迟吗?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接