import java.lang.invoke.*;
public class InvokeDynamicDemo {
public static double doubleIt(double d){
System.out.print("Doubling it");
return d*2;
}
public static void main(String[] args) throws Throwable {
MethodHandles.Lookup lookUp = MethodHandles.lookup();
MethodHandle doubleIt = lookUp.findStatic(InvokeDynamicDemo.class, "doubleIt", MethodType.methodType(double.class,double.class));
doubleIt.invokeExact(2.0D); // Exception
//doubleIt.invoke(2.0D); // No exception thrown
}
}
Run Code Online (Sandbox Code Playgroud)
线程"main"中的异常java.lang.invoke.WrongMethodTypeException:expected(double)double但在java.lang.invoke.Invokers的java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:340)中找到(double)void InvokeDynamicDemo.main中的.checkExactType(Invokers.java:351)(InvokeDynamicDemo.java:32)
这段代码出了什么问题,我无法理解.请帮忙.
问题是你没有使用invokeExact方法的结果.我之前没有见过这种方法,但看起来Java编译器必须以非常特殊的方式处理它.从MethodHandle文档:
与通常的虚方法一样,源级调用invokeExact并调用compile到invokevirtual指令.更不寻常的是,编译器必须记录实际的参数类型,并且可能不会对参数执行方法调用转换.相反,它必须根据自己未转换的类型生成将它们压入堆栈的指令.方法句柄对象本身在参数之前被压入堆栈.然后,编译器生成一个
invokevirtual指令,该指令使用描述参数和返回类型的符号类型描述符来调用方法句柄.要发出完整的符号类型描述符,编译器还必须确定返回类型.这是基于对方法调用表达式的强制转换(如果有),或者
Object如果调用是表达式,或者void如果调用是语句.演员表可以是原始类型(但不是void).
在您不使用结果的情况下调用方法时,编译器会推断您希望它是一个void方法 - 因此(double)void是异常的一部分.
如果您将呼叫更改为:
double result = (double) doubleIt.invokeExact(2.0);
Run Code Online (Sandbox Code Playgroud)
...然后编译器知道您期望的返回类型,并可以创建适当的符号类型描述符.