这个Java代码中的短路逻辑有什么问题?

时间:2009-05-12 13:18:29

标签: java logical-operators

为什么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;
}

9 个答案:

答案 0 :(得分:25)

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

如果我添加编译器使用的隐式括号

,它可能会有所帮助

编辑:正如Chris Jester-Young所说,这实际上是因为逻辑运算符必须从左到右相关联:

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

func1返回后,它变为:

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

评估短路后,或者变为:

if (true)

答案 1 :(得分:6)

根据precedence rules

评估Java函数

因为“&&”具有比“||”更高的优先级,它首先被评估,因为你没有任何括号来设置显式优先级

所以你表达了

(A || B && C) 

(T || F && F)

被放在括号中

(T || (F && F)) 

因为优先规则。

由于编译器理解如果'A == true'它不需要打扰评估表达式的其余部分,它会在评估A后停止。

如果您已将((A || B) && C)括起来,那么它会评估为假。

编辑

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

答案 2 :(得分:3)

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

答案 3 :(得分:2)

答案 4 :(得分:2)

Java使用Lazy评估。

由于Func1总是返回true,因此整个表达式必须为true,因此它会快速删除表达式的其余部分。

true || (???)

false && (???)

总是快捷方式。

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

我们可以使用这个效果很好:

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

意思是如果s为null,我们甚至不必尝试调用s.equals,并且我们不会最终抛出NullPointerException

答案 5 :(得分:2)

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

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

答案 6 :(得分:1)

简短回答:short-circuit evaluation

因为func1()yelds为true所以不需要继续评估,因为它总是正确的

答案 7 :(得分:1)

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

答案 8 :(得分:0)

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

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