No, Java has only eager evaluation for user-defined methods. Some of Java's language constructs implement non-strict evaluation as you note. Others include if
, ?:
, while
.
I once learned[1] that there is some confusion around what it means to "have lazy evaluation." First, lazy evaluation means call-by-need evaluation. Java has nothing at all like this. However, there is a common trend (which I personally discourage) to loosen the definition of lazy evaluation to also include call-by-name evaluation. Functions such as &&
cannot be distinguished under call-by-need versus call-by-name evaluation; it would be the same regardless, which obscures the matter.
Taking this loosening into account, some further counter-argue by claiming Java has lazy evaluation by the following:
interface Thunk<A> {
A value();
}
Then, you might write a user-defined &&
like so:
boolean and(boolean p, Thunk<Boolean> q) {
return p && q();
}
The claim is then put forward that this demonstrates that Java has lazy evaluation. However, this is not lazy evaluation, even in the loose sense. The distinguishing point here is that Java's type system does not unify the types boolean
/Boolean
and Thunk<Boolean>
. Attempting to use one as the other will result in a type-error. In the absence of a static type system, the code would still fail. It is this lack of unification (static typing or not) that answers the question; no, Java does not have user-defined lazy evaluation. Of course, it can be emulated as above, but this is an uninteresting observation which follows from turing-equivalence.
A language such as Scala has call-by-name evaluation, which allows a user-defined and
function which is equivalent to the regular &&
function (taking termination into account. See [1]).
// note the => annotation on the second argument
def and(p: Boolean, q: => Boolean) =
p && q
This allows:
def z: Boolean = z
val r: Boolean = and(false, z)
Note that this short program snippet terminates by providing a value. It also unifies values of type Boolean
as call-by-name. Therefore, if you subscribe to the loose definition of lazy evaluation (and again, I discourage this), you might say that Scala has lazy evaluation. I provide Scala here as a good contrast. I recommend looking at Haskell for true lazy evaluation (call-by-need).
Hope this helps!
[1] http://blog.tmorris.net/posts/a-fling-with-lazy-evaluation/