有没有办法在 Java 中禁用短路评估?

Posted

技术标签:

【中文标题】有没有办法在 Java 中禁用短路评估?【英文标题】:Is there a way to disable short circuit evaluation in Java? 【发布时间】:2013-12-23 17:44:12 【问题描述】:

假设我有这样的代码:

boolean ret = a() && b() && c() && d() && e();

通常只有在所有其他调用 a()-d() 返回 true 时才会调用 e()。是否有一些编译器或 JVM 选项可以禁用短路评估,因此无论其他函数的结果如何,都会始终调用 e()?

基本上我在做大型系统的 UAT 并且需要测试 e(),但是设置环境和场景来确保所有 a()、b() 等返回 true 是非常痛苦的......

编辑:好的,我想使用位 AND 而不是逻辑一个可以提供某种解决方法,但是理想情况下,我正在寻找一种不需要对源代码进行任何更改的解决方案。由于形式和技术原因(正如我提到的系统很大,我们有在暂存区域之间推广和部署代码并获得签核的整个过程)。这仅用于测试,生产版本需要启用惰性评估(即使用 &&)

验尸:

“正确”答案是:不,没有。 “有用”的答案:您可以将 && 更改为 & “我最后做了什么”回答:远程调试系统,在表达式上放断点并告诉 eclipse 运行 e() -_-

【问题讨论】:

只使用单字符而不是双字符。 诶!根据您的需要修改代码后,您没有要重建的编译器? @devnull:根据环境,修复设置并重新运行测试可能需要相当长的时间,因此在第一次拍摄时收集所有错误的先决条件可能是一个巨大的优势......而这也许是少数几个非短路评估的好用例之一。 为什么要这样做?如果要测试e(),为什么不直接测试e(),完全脱离这个if条件 其实我对这个设计总体感觉有点怀疑。除此之外...为什么你不能自己测试e(),为什么你觉得你需要这样做?出于测试目的,您应该设置一个允许所有其他场景返回 true 的场景。这可能涉及模拟对象或其他注入值,但您仍然应该找到一种方法来做到这一点。请注意,暂时禁用您想要的逻辑意味着您没有测试部署到生产环境的代码(因为此方法运行不同的代码)。 【参考方案1】:

为了禁用短路,请使用单个 '&' 或 '|'而不是两个:

boolean ret = a() & b() & c() & d() & e();

【讨论】:

不错的简短回答,举个例子……正是我需要的。【参考方案2】:

单 & 建议非常好 - 解释它为什么有效:

boolean ret = a() && b() && c() && d() && e();

此调用对方法的返回值使用逻辑与。它知道如果任何结果为假,则最终结果为假,因此它可以立即返回。 “惰性评估”是一种标准计算优化,可避免进行不必要的处理。

boolean ret = a() & b() & c() & d() & e();

这是用算术运算替换逻辑运算 - 位运算符。如果这适用于整数,那么它将and 整数的所有单独位一起。在布尔值的情况下,虽然只有真值或假值,但它仍然作为算术表达式计算,因此表达式的所有部分都被计算。

所以对于布尔值 & 和 && 给出相同的逻辑结果,但它们在内部的处理方式不同,这恰好给出了您正在寻找的行为。

【讨论】:

【参考方案3】:

没有用于更改布尔表达式求值语义的编译器或 JVM 选项。

如果您无法修改源,可能的(尽管不能保证)选项包括:

通过精心设计,创造性地重现您想要测试的条件 先决条件的设置。 使用模拟对象。 破解编译器。 破解 JVM。 旋转字节码。

抱歉,这些都比编译器/JVM 选项或修改源代码困难得多。此外,最后三个选项(以及请求的编译器/JVM 选项或修改源代码)违反了不修改正在测试的内容的正确测试协议。

【讨论】:

以上是关于有没有办法在 Java 中禁用短路评估?的主要内容,如果未能解决你的问题,请参考以下文章

短路评估顺序和前缀增量运算符

c中的内部短路评估

当运算符优先级说不应该时,为啥短路评估会起作用?

短路逻辑评估运算符

为啥具有短路操作的并行 Java Stream 会评估 Stream 的所有元素,而顺序 Stream 不会?

线性搜索和短路评估(运行时错误)