java - Lambda Metafactory Variable Capture -


when creating lambda manually using methodhandles.lookup, methodhandles, methodtypes, etc, how might 1 implement variable capture?

for example, no capture:

public intsupplier foo() {     return this::fortytwo; } /**  *  not virtual, oh well.  */ public int fortytwo() {     return 42; } 

and clunkier form, using stuff in java.lang.invoke:

public intsupplier foo() {     methodhandles.lookup lookup = methodhandles.lookup();     methodtype methodtype = methodtype.methodtype(int.class),                lambdatype = methodtype.methodtype(intsupplier.class);     methodhandle methodhandle = lookup.findvirtual(getclass(), "fortytwo", methodtype);     callsite callsite = lambdametafactory.metafactory(lookup, "getasint", lambdatype, methodtype, methodhandle, methodtype);     return (intsupplier) callsite.gettarget().invokeexact(); } /**  *  not virtual, oh well.  */ public int fortytwo() {     return 42; } 

would return simple, pointless intsupplier returns 42 when invoked, if 1 capture something?

the third argument bootstrap method, named lambdatype, invoked type of associated invokedynamic instruction (normally filled in jvm). it’s semantic defined bootstrap method , in case of lambdametafactory, specifies functional interface return type (the type of object construct) , values capture parameter type (the type of values consume when constructing lambda instance).

so in order capture this, have add type of this invoked type , pass this argument invokeexact call:

public class test {     public static void main(string... arg) throws throwable {         system.out.println(new test().foo().getasint());     }     public intsupplier foo() throws throwable {         methodhandles.lookup lookup = methodhandles.lookup();         methodtype methodtype  = methodtype.methodtype(int.class),                    invokedtype = methodtype.methodtype(intsupplier.class, test.class);         methodhandle methodhandle = lookup.findvirtual(getclass(), "fortytwo", methodtype);         callsite callsite = lambdametafactory.metafactory(lookup, "getasint",             invokedtype, methodtype, methodhandle, methodtype);         return (intsupplier) callsite.gettarget().invokeexact(this);     }     public int fortytwo() {         return 42;     } } 

if want capture more values, have add them signature in right order. e.g., capture int value:

public class test {     public static void main(string... arg) throws throwable {         system.out.println(new test().foo(100).getasint());     }     public intsupplier foo(int capture) throws throwable {         methodhandles.lookup lookup = methodhandles.lookup();         methodtype methodtype = methodtype.methodtype(int.class, int.class),             functiontype = methodtype.methodtype(int.class),             invokedtype = methodtype.methodtype(intsupplier.class, test.class, int.class);         methodhandle methodhandle=lookup.findvirtual(getclass(),"addfortytwo",methodtype);         callsite callsite = lambdametafactory.metafactory(lookup, "getasint",             invokedtype, functiontype, methodhandle, functiontype);         return (intsupplier) callsite.gettarget().invokeexact(this, capture);     }     public int addfortytwo(int valuetoadd) {         return 42+valuetoadd;     } } 

the target method have signature consisting of this type, if not static, followed parameter types. capture values map in order signature’s types left right , remaining parameter types, if any, contribute functional signature, hence have match interface method’s parameter types.

this implies when there no captured values , target method not static, method receiver type might become associated first type of functional signature, in tointfunction<string> f=string::length;.


Comments

Popular posts from this blog

javascript - Bootstrap Popover: iOS Safari strange behaviour -

Website Login Issue developed in magento -

Can the constants be defined inside a model file of a framework in PHP? -