【发布时间】:2015-01-02 17:39:15
【问题描述】:
我正在尝试显式使用 LambdaMetafactory.metafactory,我不明白为什么它只适用于 Runnable 功能接口。例如,此代码执行预期的操作(打印“hello world”):
public class MetafactoryTest {
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup caller = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(void.class);
MethodType invokedType = MethodType.methodType(Runnable.class);
CallSite site = LambdaMetafactory.metafactory(caller,
"run",
invokedType,
methodType,
caller.findStatic(MetafactoryTest.class, "print", methodType),
methodType);
MethodHandle factory = site.getTarget();
Runnable r = (Runnable) factory.invoke();
r.run();
}
private static void print() {
System.out.println("hello world");
}
}
当我尝试使用不同的功能接口时出现问题,例如供应商。以下代码不起作用:
public class MetafactoryTest {
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup caller = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(String.class);
MethodType invokedType = MethodType.methodType(Supplier.class);
CallSite site = LambdaMetafactory.metafactory(caller,
"get",
invokedType,
methodType,
caller.findStatic(MetafactoryTest.class, "print", methodType),
methodType);
MethodHandle factory = site.getTarget();
Supplier<String> r = (Supplier<String>) factory.invoke();
System.out.println(r.get());
}
private static String print() {
return "hello world";
}
}
Exception in thread "main" java.lang.AbstractMethodError: metafactorytest.MetafactoryTest$$Lambda$1/258952499.get()Ljava/lang/Object;
at metafactorytest.MetafactoryTest.main(MetafactoryTest.java:29)
代码的两个sn-p不应该以类似的方式工作,这是第二个sn-p代码的问题吗?
此外,应该等效的以下代码运行良好:
public class MetafactoryTest {
public static void main(String[] args) throws Throwable {
Supplier<String> r = (Supplier<String>) () -> print();
System.out.println(r.get());
}
private static String print() {
return "hello world";
}
}
编辑
另一个避免改变方法返回类型的解决方案是定义一个新的函数式接口:
public class MetafactoryTest {
@FunctionalInterface
public interface Test {
String getString();
}
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup caller = MethodHandles.lookup();
MethodType methodType = MethodType.methodType(String.class);
MethodType invokedType = MethodType.methodType(Test.class);
CallSite site = LambdaMetafactory.metafactory(caller,
"getString",
invokedType,
methodType,
caller.findStatic(MetafactoryTest.class, "print", methodType),
methodType);
MethodHandle factory = site.getTarget();
Test r = (Test) factory.invoke();
System.out.println(r.getString());
}
private static String print() {
return "hello world";
}
【问题讨论】:
-
也许问题在于您作为第二个参数传递的方法名称“run”。 Runnable 有一个“运行”方法。供应商没有。
-
这是一个错误(Runnable 案例仅适用于“run”),但在获取第二个 sn-p 时也会出现该错误。
标签: java metaprogramming java-8 lambda