java – Lambda Metafactory变量捕获
发布时间:2020-05-24 23:37:32 所属栏目:Java 来源:互联网
导读:使用MethodHandles.Lookup,MethodHandles,MethodTypes等手动创建lambda时,如何实现变量捕获? 例如,没有捕获: public IntSupplier foo() { return this::fortyTwo;}/** * Would not normally be virtual, but oh well. */public i
|
使用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 – org.codehaus.jackson.JsonParseException:意外的
- java – 将@PathParam传递给Jersey中的Sub Resource locato
- java – Lucene IndexWriter线程安全
- 解决方案时super不能成为java中的第一行构造函数
- java – 无法找到JAX-WS的Spring Namespace
- java – Hibernate异常;找到了同一个集合的两个表示
- java – 将时间戳长度转换为正常的日期格式
- 浅谈java Properties类的使用基础
- JAVA 数据结构链表操作循环链表
- java – 使用JInternalFrame在客户端/服务器应用程序中创建
