Tôi đang cố gắng sử dụng LambdaMetafactory.metafactory một cách rõ ràng, tôi không thể hiểu tại sao nó chỉ hoạt động với giao diện chức năng Runnable. Ví dụ: mã này thực hiện những gì được mong đợi (nó in "hello world"):Sử dụng rõ ràng LambdaMetafactory
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");
}
}
Sự cố phát sinh khi tôi cố gắng sử dụng giao diện chức năng khác, chẳng hạn như nhà cung cấp. Mã sau đây không hoạt động:
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)
Không phải hai đoạn mã hoạt động theo cách tương tự, đó là vấn đề trong đoạn mã thứ hai?
Hơn nữa đoạn mã sau, bạn cần phải tương đương, hoạt động tốt:
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";
}
}
Sửa
Một giải pháp mà tránh thay đổi loại phương thức hoàn trả là để xác định một giao diện chức năng mới:
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";
}
Có thể vấn đề là với tên phương thức "chạy" bạn chuyển làm đối số thứ hai. Runnable có một phương thức "chạy". Nhà cung cấp không. – Eran
Đó là lỗi (Trường hợp Runnable chỉ hoạt động với "chạy"), nhưng cũng với đoạn mã thứ hai cung cấp lỗi đó. – andrebask