简体   繁体   English

MethodHandle invokeExact使用return和parameter调用静态方法

[英]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 else void if the invocation is a statement. 这是基于方法调用表达式(如果有)的转换,或者基于Object如果调用是表达式)的转换,或者如果调用是语句的则转换为void The cast may be to a primitive type (but not void ). 强制类型转换可能是原始类型(但不是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.

相关问题 MethodHandle InvokeExact参数 - MethodHandle InvokeExact parameter 由使用MethodHandle :: invokeExact作为方法引用导致的LambdaConversionException引起的BootstrapMethodError - BootstrapMethodError caused by LambdaConversionException caused by using MethodHandle::invokeExact as a method reference 如何使用Object []数组调用MethodHandle.invokeExact()? - How to call MethodHandle.invokeExact() with an array of Object[]? MethodHandle示例在invokeExact调用时抛出WrongMethodTypeException - MethodHandle example throws WrongMethodTypeException on invokeExact call Gradle Android Error:MethodHandle.invoke和MethodHandle.invokeExact - Gradle Android Error: MethodHandle.invoke and MethodHandle.invokeExact Java 8 | 在字段上动态使用 MethodHandle#invokeExact - Java 8 | Using MethodHandle#invokeExact on fields dynamically 为什么(int)MethodHandle.invokeExact缺少checkcast-instruction? - Why checkcast-instruction is absent for (int)MethodHandle.invokeExact? 为什么即使 MethodHandle 没问题,在 invokeExact 上也会得到 WrongMethodTypeException - Why do I get a WrongMethodTypeException on invokeExact even though MethodHandle is OK 尝试在 Android 中运行 Spark:仅从 Android O 开始支持 MethodHandle.invoke 和 MethodHandle.invokeExact - Trying to run Spark in Android: MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O 错误:MethodHandle.invoke 和 MethodHandle.invokeExact 仅从 Android O (--min-api 26) 开始支持 - Erro: MethodHandle.invoke and MethodHandle.invokeExact are only supported starting with Android O (--min-api 26)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM