Convert the Handle method to a method reference (here is the function)

MethodType methodType = MethodType.methodType(void.class, ByteBuffer.class); MethodHandle handle = MethodHandles.publicLookup().findConstructor(type, methodType); Function<ByteBuffer, Object> = handle; // ??? 

Can I get the last assignment? Inverted method does not work: Is it possible to convert a method reference to a MethodHandle?

Here is another copyable example:

 new Integer("123"); MethodType methodType = MethodType.methodType(void.class, String.class); MethodHandle handle = MethodHandles.publicLookup().findConstructor(Integer.class, methodType); Function<String, Integer> function1 = Integer::new; Function<String, Integer> function2 = handle.toLambda(); // ??? 
+8
java reflection lambda java-8
source share
3 answers

This answer contains sample code showing how to convert a MethodHandle into a functional implementation of the interface using the same function, Java 8s lambda expressions, and using method references.

All about calling LambdaMetafactory.metafactory using a method handle, the required interface, and the name of a single abstract method and the required signature.

Both, the documentation of the methods and its documentation for the class are very detailed.

So, for your request, an example code might 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<String,Integer> f=(Function<String,Integer>) LambdaMetafactory.metafactory(lookup, "apply", MethodType.methodType(Function.class), methodType.generic(), handle, methodType).getTarget().invokeExact(); System.out.println(f.apply("123")); 

Here you have to take care of the types of signatures. The fourth parameter, samMethodType is of the type of the method of the original signature raw interface s, so for the raw type of Function we must implement Object apply(Object) , and instantiatedMethodType describes the Integer apply(String) method. This is why the .generic() method is called for the Type method for the fourth parameter, which converts (String)Integer to (Object)Object .

This is even more difficult for constructors, because the constructor will look for the type (String)void , while the functional type will be the same as in the case of the static method. Thus, for the static method, MethodType methods correspond to MethodType , while for the constructor we must use a different type for the search:

 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<String,Integer> f=(Function<String,Integer>) LambdaMetafactory.metafactory(lookup, "apply", MethodType.methodType(Function.class), methodType.generic(), handle, methodType).getTarget().invokeExact(); 

But this is only for completeness, for the Integer type you should not name the constructor, but it is preferable to use the valueOf method.

+12
source share

I think you will need something like:

 Function<ByteBuffer,Object> fn = (Function<ByteBuffer,Object>) MethodHandleProxies.asInterfaceInstance(Function.class, handle); 

( Normal disclaimer: didn't even compile it. Compiled it. It seems to work.)

+5
source share

Answer collection

No handle, just lambda:

 Function<String, Integer> function1 = Integer::new; System.out.println(function1.apply("1")); 

A simple (not general, not exact) solution:

 MethodType methodType = MethodType.methodType(void.class, String.class); MethodHandle handle = MethodHandles.publicLookup().findConstructor(Integer.class, methodType); Function<String, Integer> function2 = (s) -> { try { return (Integer) handle.invoke(s); } catch (Throwable t) { throw new Error(t); } }; System.out.println(function2.apply("2")); 

Using LambdaMetafactory from Holger

 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<String,Integer> function3 = (Function<String,Integer>) LambdaMetafactory.metafactory(lookup, "apply", MethodType.methodType(Function.class), methodType.generic(), handle, methodType).getTarget().invokeExact(); System.out.println(function3.apply("3")); 

Using MethodHandleProxies by Tom Hawtin

 @SuppressWarnings("unchecked") Function<String, Integer> function4 = (Function<String, Integer>) MethodHandleProxies.asInterfaceInstance(Function.class, handle); System.out.println(function4.apply("4")); 
+1
source share

All Articles