Convert MethodHandle to method reference (here Function)

前端 未结 3 1923
醉酒成梦
醉酒成梦 2021-01-01 23:02
MethodType methodType = MethodType.methodType(void.class, ByteBuffer.class);
MethodHandle handle = MethodHandles.publicLookup().findConstructor(type, methodType);

F         


        
3条回答
  •  礼貌的吻别
    2021-01-01 23:29

    «This answer» contains a code example showing how to convert a MethodHandle to a functional interface implementation using the same feature, Java 8’s lambda expressions and method references use.

    It’s all about calling LambdaMetafactory.metafactory with the method handle, the desired interface and the name of the sole abstract method and required signature.

    Both, the method’s documentation and it’s class documentation are very detailled.

    So, for your request, example code may look like this:

    MethodType methodType = MethodType.methodType(Integer.class, String.class);
    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodHandle handle = lookup.findStatic(Integer.class, "valueOf", methodType);
    Function f=(Function)
      LambdaMetafactory.metafactory(lookup, "apply",
        MethodType.methodType(Function.class), methodType.generic(),
        handle, methodType).getTarget().invokeExact();
    
    System.out.println(f.apply("123"));
    

    You have to care about the signature types here. The fourth parameter samMethodType refers the the method type of the raw interface’s functional signature, so for the raw type Function we must implement Object apply(Object) while the instantiatedMethodType describes the method Integer apply(String). That’s why the method .generic() is called on the methodType for the fourth parameter which will convert (String)Integer to (Object)Object.

    This is even trickier for constructors as the constructor will be looked up with a (String)void type while the functional type is the same as in the static method case. So for a static method the method’s MethodType matches the MethodType while for a constructor we have to use a different type for the lookup:

    MethodType methodType = MethodType.methodType(Integer.class, String.class);
    MethodHandles.Lookup lookup = MethodHandles.lookup();
    MethodHandle handle = lookup.findConstructor(
            Integer.class, MethodType.methodType(void.class, String.class));
    Function f=(Function)
      LambdaMetafactory.metafactory(lookup, "apply",
        MethodType.methodType(Function.class), methodType.generic(),
        handle, methodType).getTarget().invokeExact();
    

    But that’s only for completeness, for the type Integer you shouldn’t call the constructor but use valueOf method, preferably.

提交回复
热议问题