java – Lambda Metafactory变量捕获
发布时间:2020-12-15 03:04:55 所属栏目:Java 来源:网络整理
导读:使用MethodHandles.Lookup,MethodHandles,MethodTypes等手动创建lambda时,如何实现变量捕获? 例如,没有捕获: public IntSupplier foo() { return this::fortyTwo;}/** * Would not normally be virtual,but oh well. */public int fortyTwo() { return 42;
使用MethodHandles.Lookup,MethodHandles,MethodTypes等手动创建lambda时,如何实现变量捕获?
例如,没有捕获: public IntSupplier foo() { return this::fortyTwo; } /** * Would not normally be virtual,but oh well. */ public int fortyTwo() { return 42; } 和它的笨重形式,使用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(); } /** * Would not normally be virtual,but oh well. */ public int fortyTwo() { return 42; } 会返回一个简单的,毫无意义的IntSupplier,在调用时会返回42,但是如果想要捕获一些内容呢? 解决方法
引导程序方法的第三个参数(名为lambdaType)是关联的invokedynamic指令的调用类型(通常由JVM填充).它的语义是由bootstrap方法定义的,在LambdaMetaFactory的情况下,它将函数接口指定为返回类型(要构造的对象的类型),并将要捕获的值指定为参数类型(要使用的值的类型)构造一个lambda实例).
因此,为了捕获它,您必须将此类型添加到您调用的类型,并将其作为参数传递给invokeExact调用: 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(),methodType); CallSite callSite = LambdaMetafactory.metafactory(lookup,invokedType,methodType); return (IntSupplier) callSite.getTarget().invokeExact(this); } public int fortyTwo() { return 42; } } 如果要捕获更多值,则必须按正确的顺序将它们添加到签名中.例如,捕获另一个int值: 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),Test.class,int.class); MethodHandle methodHandle=lookup.findVirtual(getClass(),"addFortyTwo",functionType,functionType); return (IntSupplier) callSite.getTarget().invokeExact(this,capture); } public int addFortyTwo(int valueToAdd) { return 42+valueToAdd; } } 目标方法将具有由此类型组成的签名(如果不是静态的),后跟所有参数类型.捕获值将从左到右映射到此签名的类型,其余参数类型(如果有)对功能签名有贡献,因此必须匹配接口方法的参数类型. 这意味着当没有捕获的值并且目标方法不是静态时,方法接收器类型可能与第一类型的功能签名相关联,如ToIntFunction< String>中所示. F =字符串::长度;. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
相关内容
- java – ant – 禁用Ivy以获取每次运行的依赖关系
- Java DateFormat:如何处理“st”,“nd”,“rd”,“th”?
- 如果lisp中的字符串是向量,为什么我不能使用svref访问第一个
- java的类构造函数可以访问哪些变量
- 详解Spring MVC拦截器实现session控制
- java – 如何在Spring上运行EnableScheduling注释来重新启动
- Java IPv6地址字符串到字节
- java – Hql“in”语句不适用于@ElementCollection
- java – Zoomable JScrollPane – setViewPosition无法更新
- Java 继承 LinkedHashMap 实现LRU算法