[英]MethodHandle invokeExact a static method with return and parameter
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
}
}
Exception in thread "main" java.lang.invoke.WrongMethodTypeException: expected (double)double but found (double)void at java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:340) at java.lang.invoke.Invokers.checkExactType(Invokers.java:351) at InvokeDynamicDemo.main(InvokeDynamicDemo.java:32) 线程“主”中的异常java.lang.invoke.WrongMethodTypeException:预期为(double)double,但在java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:340)处为(double)void在java.lang.invoke.Invokers .checkExactType(Invokers.java:351)位于InvokeDynamicDemo.main(InvokeDynamicDemo.java:32)
What is wrong with this code , I can't figure it. 此代码有什么问题,我无法理解。 Please help. 请帮忙。
The problem is that you're not using the result of the invokeExact
method. 问题是您没有使用invokeExact
方法的结果。 I hadn't seen this method before, but it looks like the Java compiler has to handle it in a very special way. 我以前没有看过这种方法,但是看起来Java编译器必须以一种非常特殊的方式来处理它。 From the MethodHandle
documentation : 从MethodHandle
文档中 :
As is usual with virtual methods, source-level calls to invokeExact and invoke compile to an invokevirtual instruction. 与虚拟方法一样,源代码级的invokeExact调用和编译编译为invokevirtual指令。 More unusually, the compiler must record the actual argument types, and may not perform method invocation conversions on the arguments. 更不寻常的是,编译器必须记录实际的参数类型,并且不能对参数执行方法调用转换。 Instead, it must generate instructions that push them on the stack according to their own unconverted types. 相反,它必须生成指令,以根据其自身未转换的类型将其压入堆栈。 The method handle object itself is pushed on the stack before the arguments. 方法句柄对象本身在参数之前被压入堆栈。 The compiler then generates an
invokevirtual
instruction that invokes the method handle with a symbolic type descriptor which describes the argument and return types. 然后,编译器会生成一个invokevirtual
指令,该指令将使用描述参数和返回类型的符号类型描述符来调用方法句柄。To issue a complete symbolic type descriptor, the compiler must also determine the return type. 要发布完整的符号类型描述符,编译器还必须确定返回类型。 This is based on a cast on the method invocation expression, if there is one, or else
Object
if the invocation is an expression, or elsevoid
if the invocation is a statement. 这是基于方法调用表达式(如果有)的转换,或者基于Object
如果调用是表达式)的转换,或者如果调用是语句的则转换为void
。 The cast may be to a primitive type (but notvoid
). 强制类型转换可能是原始类型(但不是void
)。
At the moment you're calling the method without using the result, so the compiler infers that you expect it to be a void
method - hence the (double)void
part of the exception. 此刻,您在不使用结果的情况下调用该方法,因此编译器推断您期望它是一个void
方法-因此是异常的(double)void
部分。
If you change the call to: 如果将呼叫更改为:
double result = (double) doubleIt.invokeExact(2.0);
... then the compiler knows what return type you're expecting, and can create the appropriate symbolic type descriptor. ...然后编译器知道您期望的返回类型,并可以创建适当的符号类型描述符。
From Oracle Documentation , it says that invokeExact
method Invokes the method handle, allowing any caller type descriptor, but requiring an exact type match. 从Oracle文档中可以看出, invokeExact
方法调用方法句柄,允许任何调用者类型描述符,但需要完全匹配的类型。 The symbolic type descriptor at the call site of invokeExact must exactly match this method handle's type. invokeExact的调用站点上的符号类型描述符必须与该方法句柄的类型完全匹配。 No conversions are allowed on arguments or return values. 不允许对参数或返回值进行任何转换。
But, invoke
method Invokes the method handle, allowing any caller type descriptor, and optionally performing conversions on arguments and return values. 但是, invoke
方法调用方法句柄,允许任何调用者类型描述符,并可以选择对参数和返回值执行转换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.