Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/329.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java MethodHandle强制转换返回类型_Java_Methodhandle - Fatal编程技术网

Java MethodHandle强制转换返回类型

Java MethodHandle强制转换返回类型,java,methodhandle,Java,Methodhandle,我尝试通过methodhandles将方法链接在一起,其中一些方法来自泛型类型。如果函数返回泛型类型,我必须为MethodType指定Object.class,但我认为没有简单的方法将其转换回泛型类型参数类型。在大多数情况下,这并没有问题,因为invoke似乎会自动转换它们,但我必须创建mhs,它可以使用invokeExact运行。没有简单的方法可以使用methodhandles进行强制转换吗 我的测试代码: public static void main(String[] args) thro

我尝试通过methodhandles将方法链接在一起,其中一些方法来自泛型类型。如果函数返回泛型类型,我必须为MethodType指定Object.class,但我认为没有简单的方法将其转换回泛型类型参数类型。在大多数情况下,这并没有问题,因为invoke似乎会自动转换它们,但我必须创建mhs,它可以使用invokeExact运行。没有简单的方法可以使用methodhandles进行强制转换吗

我的测试代码:

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));
}
publicstaticvoidmain(String[]args)抛出Throwable{
类前缀器{
公共静态字符串前缀(字符串s){
返回“编号:”+s;
}
}
IntFunction 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(转换器);
/*无法工作,因为转换器是(int)对象且没有(int)字符串
var mh=MethodHandles.filterArguments(prefixMH,0,converterMH);
*/
/*不适用于invoke,但不适用于invokeExact
var prefixCasted=MethodHandles.explicitCastArguments(prefixMH,MethodType.MethodType(String.class,Object.class));
var mh=MethodHandles.filterArguments(prefixCasted,0,converterMH);
*/
/*不适用于invoke,但不适用于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));
}

我觉得您当前的代码还可以,您只需在呼叫站点使用一个cast即可:

System.out.println((String) mh.invokeExact(42));
否则,调用站点上的类型将是
(int)Object
,它与MethodHandle
(int)字符串的类型不匹配,您将得到一个WMTE

调用您的呼叫的
版本:

System.out.println(mh.invoke(12));
将使用
asType
调用将
mh
的类型隐式转换为
(int)对象
(调用站点的类型),然后调用生成的方法句柄

如果要显式执行此操作并使用
invokeExact
,可以执行以下操作:

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