&安培;&安培; (AND)和|| (或)在IF声明中

时间:2009-11-25 09:50:13

标签: java if-statement

我有以下代码:

if(!partialHits.get(req_nr).containsKey(z) || partialHits.get(req_nr).get(z) < tmpmap.get(z)){  
    partialHits.get(z).put(z, tmpmap.get(z));  
}

其中partialHits是HashMap。
如果第一个语句为真,会发生什么? Java是否仍会检查第二个语句?因为为了使第一个语句为真,HashMap不应该包含给定的键,因此如果选中第二个语句,我将获得NullPointerException 所以简单来说,如果我们有以下代码

if(a && b)  
if(a || b)
如果b在第一种情况下为假,并且a在第二种情况下为真,那么Java会检查a吗?

9 个答案:

答案 0 :(得分:185)

不,它不会被评估。这非常有用。例如,如果您需要测试String是否为空或空,则可以编写:

if (str != null && !str.isEmpty()) {
  doSomethingWith(str.charAt(0));
}

或者,反过来说

if (str == null || str.isEmpty()) {
  complainAboutUnusableString();
} else {
  doSomethingWith(str.charAt(0));
}

如果我们在Java中没有“短路”,我们会在上面的代码行中收到很多NullPointerExceptions。

答案 1 :(得分:62)

Java有5种不同的布尔比较运算符:&amp;,&amp;&amp;,|,||,^

&安培;和&amp;&amp;是“和”运营商,|和|| “或”运算符,^是“xor”

在检查参数值之前,单个参数将检查每个参数,无论值如何。 双重参数将首先检查左参数及其值,如果true||)或false&&)保持第二个不变。 声音是否合并?一个简单的例子应该清楚说明:

给出所有示例:

 String aString = null;

 if (aString != null & aString.equals("lala"))

在评估完成之前检查这两个参数,并为第二个参数抛出NullPointerException。

 if (aString != null && aString.equals("lala"))

检查第一个参数并返回false,因此不会检查第二个参数,因为无论如何结果都是false

OR的相同:

 if (aString == null | !aString.equals("lala"))

也会引发NullPointerException。

 if (aString == null || !aString.equals("lala"))

检查第一个参数并返回true,因此不会检查第二个参数,因为无论如何结果都是true

XOR无法优化,因为它取决于两个参数。

答案 2 :(得分:26)

不会不会被检查。此行为称为short-circuit evaluation,是许多语言(包括Java)的一项功能。

答案 3 :(得分:19)

这里的所有答案都很棒,但是,为了说明这些问题的来源,对于这样的问题,最好转到源代码:Java语言规范。

Section 15:23, Conditional-And operator (&&),说:

  

&amp;&amp;运营商就像&amp; (§15.22.2),但仅在其左侧操作数的值为真时才计算其右侧操作数。 [...]在运行时,如果结果值为false,则条件和表达式的值为false,并且不评估右侧操作数表达式,则首先计算左侧操作数表达式[...] 。如果左侧操作数的值为true,则评估右侧表达式[...]结果值将成为条件和表达式的值。因此,&amp;&amp;计算与&amp;相同的结果在布尔操作数上。它的不同之处仅在于有条件地而不是总是评估右侧操作数表达式。

同样地,Section 15:24, Conditional-Or operator (||)说:

  

||运算符就像| (§15.22.2),但仅当其左侧操作数的值为false时才计算其右侧操作数。 [...]在运行时,首先评估左侧操作数表达式; [...]如果结果值为true,则条件或表达式的值为true,并且不评估右侧操作数表达式。如果左侧操作数的值为false,则评估右侧表达式; [...]结果值成为条件或表达式的值。因此,||计算与|相同的结果在布尔或布尔操作数上。它的不同之处仅在于有条件地而不是总是评估右侧操作数表达式。

有点重复,也许,但最好的确认它们是如何工作的。类似地,条件运算符(?:)仅评估适当的“half”(如果值为true则为左半部分,如果为false则为右半部分),允许使用如下表达式:

int x = (y == null) ? 0 : y.getFoo();

没有NullPointerException。

答案 4 :(得分:6)

不,如果a为真(在or测试中),则不会测试b,因为测试结果将始终为真,无论b表达式的值是什么。

做一个简单的测试:

if (true || ((String) null).equals("foobar")) {
    ...
}

抛出NullPointerException

答案 5 :(得分:5)

此处短路意味着不会评估第二个条件。

如果A为假,(A&amp;&amp; B)将导致短路。

如果A为真,如果(A&amp;&amp; B)导致短路。

如果A为真,则(A || B)将导致短路。

如果A为假,如果(A || B)会导致短路。

答案 6 :(得分:4)

不,不会,一旦知道结果,Java就会短路并停止评估。

答案 7 :(得分:4)

是的,布尔表达式的短路评估是所有C类家族的默认行为。

一个有趣的事实是,Java还使用&|作为逻辑操作数(它们被重载,int类型,它们是预期的按位运算)来评估所有术语在表达式中,当您需要副作用时也很有用。

答案 8 :(得分:0)

这可以追溯到&amp;和和&amp;&amp;,|和||

顺便说一句,你多次执行相同的任务。不确定效率是否是一个问题。你可以删除一些重复。

Z z2 = partialHits.get(req_nr).get(z); // assuming a value cannout be null.
Z z3 = tmpmap.get(z); // assuming z3 cannot be null.
if(z2 == null || z2 < z3){   
    partialHits.get(z).put(z, z3);   
}