不,Java 只对用户定义的方法进行热切评估。正如您所注意到的,一些 Java 语言结构实现了非严格评估。其他包括if
, ?:
, while
。
我曾经了解到[1] 关于“进行惰性评估”的含义存在一些混淆。首先,惰性求值意味着按需调用。Java 根本没有这样的东西。然而,有一个普遍的趋势(我个人不鼓励)放宽惰性评估的定义,也包括按名称调用的评估。诸如&&
在按需调用与按名称调用评估下无法区分的功能;无论如何都是一样的,这使事情变得模糊不清。
考虑到这种松动,一些进一步的反驳声称 Java 具有以下惰性评估:
interface Thunk<A> {
A value();
}
然后,您可以&&
像这样编写用户定义:
boolean and(boolean p, Thunk<Boolean> q) {
return p && q();
}
然后提出声称这表明 Java 具有惰性求值。然而,即使在松散的意义上,这也不是懒惰的评价。这里的区别在于Java的类型系统没有统一类型boolean
/Boolean
和Thunk<Boolean>
. 尝试将一个用作另一个将导致type-error。在没有静态类型系统的情况下,代码仍然会失败。正是这种缺乏统一性(静态类型与否)回答了这个问题;不,Java 没有用户定义的惰性求值。当然,它可以像上面那样模拟,但这是从图灵等价得出的一个无趣的观察。
诸如 Scala 之类的语言具有按名称调用评估,它允许用户定义的and
函数等效于常规&&
函数(考虑终止。参见 [1])。
// note the => annotation on the second argument
def and(p: Boolean, q: => Boolean) =
p && q
这允许:
def z: Boolean = z
val r: Boolean = and(false, z)
请注意,这个简短的程序片段通过提供一个值来终止。它还将类型的值统一Boolean
为按名称调用。因此,如果你赞同惰性求值的松散定义(同样,我不鼓励这样做),你可能会说 Scala 具有惰性求值。我在这里提供 Scala 作为一个很好的对比。我建议查看 Haskell 以获得真正的惰性评估(按需调用)。
希望这可以帮助!
[1] http://blog.tmorris.net/posts/a-fling-with-lazy-evaluation/