8

为什么 func3 在下面的程序中没有被执行?在func1之后,func2不需要被评估但是对于func3,不是吗?

if (func1() || func2() && func3()) {
        System.out.println("true");
    } else {
        System.out.println("false");
    }
}

public static boolean func1() {
    System.out.println("func1");
    return true;
}

public static boolean func2() {
    System.out.println("func2");
    return false;
}

public static boolean func3() {
    System.out.println("func3");
    return false;
}
4

9 回答 9

25

您正在使用短路或。如果第一个参数为真,则整个表达式为真。

如果我添加编译器使用的隐式括号可能会有所帮助

编辑:正如 Chris Jester-Young 所指出的,这实际上是因为逻辑运算符必须具有从左到右的关联性:

if (func1() || (func2() && func3()))

func1返回后变成这样:

if (true || (func2() && func3()))

在评估短路或之后,它变为:

if (true)
于 2009-05-12T13:21:06.053 回答
6

Java 函数根据优先级规则进行评估

因为“&&”的优先级高于“||”,所以首先评估它,因为您没有任何括号来设置显式优先级

所以你的表情

(A || B && C) 

这是

(T || F && F)

括号内为

(T || (F && F)) 

因为优先规则。

由于编译器知道如果 'A == true' 它不需要计算表达式的其余部分,它会在计算 A 后停止。

如果你用括号括起来((A || B) && C),那么它将评估为假。

编辑

另一种方法,正如其他海报所提到的,是使用“|” 和“&”而不是“||” 和“&&”,因为这会阻止表达式的快捷方式。但是,由于优先规则,最终结果仍然是相同的。

于 2009-05-12T13:28:40.530 回答
3

Java 使布尔表达式短路。这意味着,一旦func1()执行并返回true,布尔值的其余部分就无关紧要,因为您使用的是or运算符。无论func2() && func3()计算结果如何,整个表达式都将计算为true。因此,Java 甚至不费心评估func2()or func3()

于 2009-05-12T13:20:48.173 回答
2

http://en.wikipedia.org/wiki/Short-circuit_evaluation

于 2009-05-12T13:21:23.633 回答
2

Java 使用惰性求值。

由于 Func1 总是返回 true,整个表达式必须为 true,所以它会简化表达式的其余部分。

true || (???)

false && (???)

总会走捷径。

要关闭快捷方式评估,请使用 | 和 & 而不是 || 和 &&

我们可以使用它来达到很好的效果:

String s;
if (s != null && !s.equals("")) ...

这意味着如果 s 为 null,我们甚至不必尝试调用 s.equals,也不会最终抛出 NullPointerException

于 2009-05-12T13:23:30.117 回答
2

您正在使用快捷操作符 || 和 &&。如果结果已经定义,这些运算符不会执行表达式的其余部分。对于 || 这意味着如果第一个表达式为真,对于 && 如果第一个表达式为假。

如果要执行表达式的所有部分,请使用 | 而 & 相反,这不是捷径。

于 2009-05-12T13:25:00.583 回答
1

简短回答:短路评估

由于 func1() 为真,因此无需继续评估,因为它始终为真

于 2009-05-12T13:21:15.210 回答
1

如果函数 1 总是返回 true,那么 Java 不需要评估表达式的其余部分来确定整个表达式是否为 true。

于 2009-05-12T13:22:34.910 回答
0

如果要执行所有功能,可以删除快捷方式

if (func1() | func2() & func3()) {
于 2009-05-12T18:37:44.480 回答