Я пытался проверить, можно ли использовать MethodHandle::invoke или MethodHandle::invokeExact в качестве ссылок на методы для функционального интерфейса, который принимает MethodHandle и возвращает сгенерированный вывод.
(Я знаю, что invoke и invokeExact являются полиморфными сигнатурами, отсюда и вызов метафабрики в InvokeExact. Однако я хотел знать, может ли компилятор исключить то, что мне нужно было сделать, чтобы получить подходящую версию invoke/invokeExact. .)
invoke.InvokeExact0
package invoke;
import java.lang.invoke.MethodHandle;
import static java.lang.System.out;
import static java.lang.invoke.LambdaMetafactory.metafactory;
import static java.lang.invoke.MethodHandles.lookup;
import static java.lang.invoke.MethodType.methodType;
@FunctionalInterface
public interface InvokeExact0<OUTPUT> {
public OUTPUT invokeExact(MethodHandle methodHandle) throws Throwable;
public static <OUTPUT> InvokeExact0<OUTPUT> new_(InvokeExact0<OUTPUT> invokeExact) {
return invokeExact;
}
public static void main(String... arguments) throws Throwable {
out.println(
(InvokeExact0<String>) metafactory(
lookup(),
"invokeExact",
methodType(InvokeExact0.class),
methodType(
Object.class,
MethodHandle.class
),
lookup().findVirtual(
MethodHandle.class,
"invokeExact",
methodType(String.class)
),
methodType(
String.class,
MethodHandle.class
)
)
.getTarget()
.invokeExact()
);
out.println(InvokeExact0.new_(MethodHandle::invokeExact));
}
}
Результат
invoke.InvokeExact0$$Lambda$1/1878246837@5ca881b5
Exception in thread "main" java.lang.BootstrapMethodError: call site initialization exception
at java.lang.invoke.CallSite.makeSite(CallSite.java:328)
at java.lang.invoke.MethodHandleNatives.linkCallSite(MethodHandleNatives.java:296)
at invoke.InvokeExact0.main(InvokeExact0.java:41)
Caused by: java.lang.invoke.LambdaConversionException: Incorrect number of parameters for instance method invokeVirtual java.lang.invoke.MethodHandle.invokeExact:(MethodH
andle)Object; 0 captured parameters, 1 functional interface method parameters, 1 implementation parameters
at java.lang.invoke.AbstractValidatingLambdaMetafactory.validateMetafactoryArgs(AbstractValidatingLambdaMetafactory.java:193)
at java.lang.invoke.LambdaMetafactory.metafactory(LambdaMetafactory.java:303)
at java.lang.invoke.CallSite.makeSite(CallSite.java:289)
... 2 more
Хорошая новость заключается в том, что с помощью метафабрики удалось синтезировать работающий экземпляр функционального интерфейса (в напечатанном виде: invoke.InvokeExact0$$Lambda$1/1878246837@1be6f5c3). Плохая новость заключается в том, что подход со ссылкой на метод привел к LambdaConversionException, что, в свою очередь, привело к BootstrapMethodError.
Затем я хотел бы спросить, как я должен интерпретировать сведения об ошибке в LambdaConversionException, поскольку обходной путь метафабрики все равно существует.