简体   繁体   English

MethodHandle 强制转换返回类型

[英]MethodHandle cast return type

I try to link methods together through methodhandles, some of them are from generic types.我尝试通过方法句柄将方法链接在一起,其中一些来自泛型类型。 If a function returns a generic type I have to specify Object.class for the MethodType but I see no easy way to convert it back into the generic type parameter type.如果 function 返回泛型类型,我必须为 MethodType 指定 Object.class ,但我认为没有简单的方法将其转换回泛型类型参数类型。 In most cases it's no problem because invoke seem to convert them automatically but I must create mhs which could be run with invokeExact.在大多数情况下,这没有问题,因为invoke 似乎会自动转换它们,但我必须创建可以使用invokeExact 运行的mhs。 Is there no easy way to cast with methodhandles?没有简单的方法来使用方法句柄进行转换吗?

My testcode:我的测试代码:

public static void main(String[] args) throws Throwable {
    class Prefixer {
        public static String prefix(String s) {
            return "Number: " + s;
        }
    }
    IntFunction<String> converter = Integer::toString;

    var lookup = MethodHandles.lookup();
    var prefixMH = lookup.findStatic(Prefixer.class, "prefix", MethodType.methodType(String.class, String.class));

    var converterMH = lookup.findVirtual(IntFunction.class, "apply", MethodType.methodType(Object.class, int.class));
    converterMH = converterMH.bindTo(converter);

    /* Doesn't work because converter is a (int)Object and no (int)String
    var mh = MethodHandles.filterArguments(prefixMH, 0, converterMH);
     */

    /* Does work for invoke but not for invokeExact
    var prefixCasted = MethodHandles.explicitCastArguments(prefixMH, MethodType.methodType(String.class, Object.class));
    var mh = MethodHandles.filterArguments(prefixCasted, 0, converterMH);
    */
    /* Does work for invoke but not for invokeExact */
    var mh = MethodHandles.filterArguments(prefixMH, 0, converterMH.asType(MethodType.methodType(String.class, int.class)));

    System.out.println(mh.invoke(12));
    System.out.println(mh.invokeExact(42));
}

Your current code looks okay to me, you just need to use a cast at the call site as well:您当前的代码对我来说看起来不错,您只需要在调用站点使用演员表:

System.out.println((String) mh.invokeExact(42));

Otherwise the type at the call site will be (int)Object which doesn't match the type of the MethodHandle (int)String and you get a WMTE.否则,调用站点的类型将是(int)Object ,它与 MethodHandle (int)String的类型不匹配,您将获得 WMTE。

The invoke version of the call you have:您拥有的调用的invoke版本:

System.out.println(mh.invoke(12));

Will implicitly convert the type of mh into (int)Object (the type of the call site) using an asType call, and then invoke the resulting method handle.将使用asType调用将mh的类型隐式转换为(int)Object (调用站点的类型),然后调用生成的方法句柄。

If you want to do that explicitly and use invokeExact you could do:如果你想明确地这样做并使用invokeExact你可以这样做:

mh = mh.asType(MethodType.methodType(Object.class, int.class));
System.out.println(mh.invokeExact(42));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM