不,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>
这两种类型统一起来。试图将它们中的一个用作另一个将导致类型错误。在没有静态类型系统的情况下,代码仍然会失败。正是这种缺乏统一性(无论是静态类型还是非静态类型),回答了这个问题;不,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/
return a && b
可能会忽略 b,但是return a & b
也将执行关系的第二部分。 - Simeon