SAM identity or at least equals/hashCode
Peter Levart
peter.levart at marand.si
Tue Jun 21 07:06:13 PDT 2011
On 06/21/11, Brian Goetz wrote:
> >> If you want to refer to the object instance that is the result of
> >> SAM conversion, call that the SAM instance or the SAM object --
> >> which is an object. (You can't assume much about its identity --
> >> the compiler will likely make sure that all instances of
> >> "stateless" lambdas are really the same object, a la the
> >> "Flyweight" pattern.)
> >
> > Only stateless? Why?
>
> Lambdas can capture final local variables. Consider:
>
> public IntFactory constGenerator(int x) { return #{ -> x } };
>
This is exactly the use case I'm talking about. One would want that
constGenerator(12).equals(constGenerator(12)) would evaluate to true and
constGenerator(12).equals(constGenerator(13)) would evaluate to false
event though the instances of two SAM objects returned from two invocations of method:
constGenerator(12)
are not the same instance, they could be equal.
> Clients will call the resulting IntFactory with
> foo.make()
> and expect an int to come back. The SAM-converted lambda is an object,
> it has to have a nilary make() method, that method has captured state x,
> so where do we store the captured state?
>
I belive you (could) generate a static method with one formal parameter:
private static int lambda$1(Integer p1) { return p1; }
...then obtain a MethodHandle for it, say: lambda$1Mh
...then capture the final x: lambda$1BoundMh = lambda$1Mh.bindTo(x);
now the SAM-converted lambda object has a reference to lambda$1BoundMh. It uses it to delegate the invocation of it's nilary make() method to. So why could it not use it to delegate equals/hashCode methods too? The prerequisite is of course that MethodHandle(s) define meaningfull equals/hashCode methods that take into account the captured (bound) state and any final target method identity too. That's what I had in mind.
For the above example, lambda$1BoundMh would implement equals/hashCode in terms of delegating to bound Object (Integer in our case) and to the wrapped MH lambda$1Mh. The final lambda$1Mh would implement equals/hashCode in terms of target lambda$1 method signature.
Now, I don't know much about MHs and how they are implemented and optimized in the VM, so perhaps such scheme would defeat those optimizations. Or is it still possible?
Regards, Peter
More information about the lambda-dev
mailing list