«This answer» 包含一个代码示例,展示了如何使用 Java 8 的 lambda 表达式和方法引用使用的相同功能将 MethodHandle 转换为函数式 interface 实现。
这一切都是关于使用方法句柄、所需接口和唯一abstract 方法的名称和所需签名来调用LambdaMetafactory.metafactory。
method’s documentation 和 it’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)。这就是为什么方法 .generic() 会在第四个参数的 methodType 上调用,这会将 (String)Integer 转换为 (Object)Object。
这对于构造函数来说更加棘手,因为构造函数将使用 (String)void 类型查找,而 功能类型 与 static 方法案例中的相同。所以对于 static 方法,方法的 MethodType 匹配 MethodType 而对于构造函数,我们必须使用不同的类型进行查找:
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 方法。