The JavaDoc for the LambdaMetaFactory
of Java 1.8 specifies that lambda capture "may involve allocation of a new function object, or may return an existing function object", but it doesn't specify when and under what circumstances it might choose one way or the other.
Looking at the actual implementation of the LambdaMetaFactory
, on the other hand, it is clear that it happens if and only if the lambda expression captures no parameters.
What I'm wondering is, is this behavior actually specified somewhere (outside of the JavaDoc) and can be relied upon? It would be nice to know whether I can rely on a lambda expression's identity being constant or not.
There is essentially no contract that covers the identity of objects that result from evaluating a lambda expression. This is covered in the JLS section 15.27.4, Run-time Evaluation of Lambda Expressions. This section explicitly leaves unspecified the exact behavior of creation vs reuse of lambda objects. The rationale from that section explains this well:
You can, of course, experiment with the implementation, call
equals()
or use==
on lambda objects, put them intoIdentityHashMaps
, etc., but since these exact behaviors are unspecified, your program may change its behavior (i.e., break) when run on different versions of the JDK or on different implementations of Java SE.I read the exchange in the comments below the question but I don't really have anything more to offer. Perhaps if you explain what you're trying to do, we could come up with some suggestions for alternatives to using lambdas as keys in a map.
You should separate behavior from identity. Lambdas can be used to implement behavior while a single ordinary class can be used to implement identity by creating instances out of it. The following simplified example derived from your code should illustrate it: