java - 将 MethodHandle 转换为方法引用(此处为 Function)

标签 java reflection lambda java-8 invokedynamic

MethodType methodType = MethodType.methodType(void.class, ByteBuffer.class);
MethodHandle handle = MethodHandles.publicLookup().findConstructor(type, methodType);

Function<ByteBuffer, Object> = handle; // ???

最后的assignment作业能拿到吗?倒置的方式不起作用:Is it possible to convert method reference to MethodHandle?

这里是另一个可复制粘贴的例子:

new Integer("123");

MethodType methodType = MethodType.methodType(void.class, String.class);
MethodHandle handle = MethodHandles.publicLookup().findConstructor(Integer.class, methodType);

Function<String, Integer> function1 = Integer::new;
Function<String, Integer> function2 = handle.toLambda(); // ???

最佳答案

«This answer»包含一个代码示例,展示如何使用相同的功能将 MethodHandle 转换为功能性 interface 实现,Java 8 的 lambda 表达式和方法引用使用。

都是关于调用LambdaMetafactory.metafactory带有方法句柄、所需接口(interface)和唯一抽象方法的名称以及所需的签名。

两者,method’s documentationit’s class documentation非常详细。

因此,根据您的要求,示例代码可能如下所示:

MethodType methodType = MethodType.methodType(Integer.class, String.class);
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle handle = lookup.findStatic(Integer.class, "valueOf", methodType);
Function<String,Integer> f=(Function<String,Integer>)
  LambdaMetafactory.metafactory(lookup, "apply",
    MethodType.methodType(Function.class), methodType.generic(),
    handle, methodType).getTarget().invokeExact();

System.out.println(f.apply("123"));

你必须关心这里的签名类型。第四个参数 samMethodType 指的是原始 interface 函数签名的方法类型,所以对于原始类型 Function 我们必须实现 Object apply(Object)instantiatedMethodType 描述方法 Integer apply(String)。这就是为什么在 methodType 上调用方法 .generic() 的第四个参数,它将把 (String)Integer 转换为 (Object)Object .

这对于构造函数来说更加棘手,因为将使用 (String)void 类型查找构造函数,而 函数类型 中的相同static 方法案例。因此,对于 static 方法,方法的 MethodTypeMethodType 匹配,而对于构造函数,我们必须使用不同的类型进行查找:

MethodType methodType = MethodType.methodType(Integer.class, String.class);
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle handle = lookup.findConstructor(
        Integer.class, MethodType.methodType(void.class, String.class));
Function<String,Integer> f=(Function<String,Integer>)
  LambdaMetafactory.metafactory(lookup, "apply",
    MethodType.methodType(Function.class), methodType.generic(),
    handle, methodType).getTarget().invokeExact();

但这只是为了完整性,对于 Integer 类型,您不应该调用构造函数,而最好使用 valueOf 方法。

关于java - 将 MethodHandle 转换为方法引用(此处为 Function),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27417634/

相关文章:

Java流: sorting by ZoneDateTime field

c++ - 管道中 lambda 的意外生命周期

java - Joincolumn 返回空值

java - 在同一个项目中使用 gradle war 和 ear 插件是否可能/明智?

c# - Type.GetType 在作为方法组而不是在 lambda 表达式中调用时失败

c# - 如何迭代泛型中的所有 DbSet?

c++ - 在每个实例化中使用 lambda 作为唯一默认参数的模板

java - 正弦的多项式逼近中的这些系数是如何确定的?

java - 尝试计算 Pi,但只得到 1

c# - 如何设置默认的 NHibernate CommandTimeOut 默认值