MethodHandle使用return和parameter调用一个静态方法

时间:2017-12-16 07:33:58

标签: java methodhandle

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          
    }
}
  

线程“main”中的异常java.lang.invoke.WrongMethodTypeException:expected(double)double但found(double)void           at java.lang.invoke.Invokers.newWrongMethodTypeException(Invokers.java:340)           at java.lang.invoke.Invokers.checkExactType(Invokers.java:351)           在InvokeDynamicDemo.main(InvokeDynamicDemo.java:32)

这段代码有什么问题,我无法理解。请帮忙。

2 个答案:

答案 0 :(得分:8)

问题是您没有使用invokeExact方法的结果。我之前没有见过这种方法,但看起来Java编译器必须以非常特殊方式处理它。来自MethodHandle documentation

  

与虚方法一样,源代码调用invokeExact并调用compile到invokevirtual指令。更不寻常的是,编译器必须记录实际的参数类型,并且可能不会对参数执行方法调用转换。相反,它必须根据自己未转换的类型生成将它们压入堆栈的指令。方法句柄对象本身在参数之前被压入堆栈。然后,编译器生成一个invokevirtual指令,该指令使用描述参数和返回类型的符号类型描述符调用方法句柄。

     

要发出完整的符号类型描述符,编译器还必须确定返回类型。这是基于对方法调用表达式的强制转换(如果有),或者如果调用是表达式则为Object,如果调用是语句,则为void cast可以是原始类型(但不是void)。

当您在不使用结果的情况下调用方法时,编译器会推断您希望它是void方法 - 因此是异常的(double)void部分。

如果您将通话更改为:

double result = (double) doubleIt.invokeExact(2.0);

...然后编译器知道你期望的返回类型,并且可以创建适当的符号类型描述符。

答案 1 :(得分:0)

Oracle Documentation开始,它表示invokeExact方法调用方法句柄,允许任何调用者类型描述符,但需要精确的类型匹配。 invokeExact调用站点上的符号类型描述符必须与此方法句柄的类型完全匹配。 参数或返回值不允许转换。

但是,invoke方法调用方法句柄,允许任何调用者类型描述符,可选地对参数执行转换并返回值。