The use of method handle in Java 7

Keywords: Java Mybatis Spring

Before JDK6, we used java reflection to implement dynamic method calls. Most frameworks use more reflection, such as mybatis, spring, etc. In JDK7, java.lang.invoke.MethodHandle (method handle) is added, which is called "modern reflection". In fact, reflection and java.lang.invoke.MethodHandle are both indirect ways to call methods, but java.lang.invoke.MethodHandle is more concise than reflection, and a lot of redundant code can be written with reflection function.

Interpretation given by the official api:

A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values.

Let's take an example to call toString() method with MethodHandle:

package org.zwc.methodhandletest;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;


/**
 * Created by zhangwenchao on 2018/1/3.
 */
public class MHTest {


    public String toString(String s) {

        return "hello," + s + "MethodHandle";
    }


    public static void main(String[] args) {
        MHTest mhTest = new MHTest();
        MethodHandle mh = getToStringMH();  //Get method handle
       
        try {
            // 1. Call method:
            String result = (String) mh.invokeExact(mhTest, "ssssss");  //Call the method according to the method handle -- note that the return value must be forced
            System.out.println(result);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }


        // 2.or like this:
        try {
            MethodHandle methodHandle2 = mh.bindTo(mhTest);
            String toString2 = (String) methodHandle2.invokeWithArguments("sssss");
            System.out.println(toString2);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }


        // Get the different representations of the current Class, the last one is the best. In general, we use SLF4J to get logger in static context.
        System.out.println(MHTest.class);
        System.out.println(mhTest.getClass());
        System.out.println(MethodHandles.lookup().lookupClass()); // like getClass()


    }

    /**
     * Get method handle
     * @return
     */
    public static MethodHandle getToStringMH() {

        MethodType mt = MethodType.methodType(String.class, String.class);  //Get method type parameters as: 1. Return value type, 2 parameter type in method

        MethodHandle mh = null;
        try {
            mh = MethodHandles.lookup().findVirtual(MHTest.class, "toString", mt);  //Find method handle
        } catch (NoSuchMethodException | IllegalAccessException e) {
            e.printStackTrace();
        }

        return mh;
    }
}

Execution result:

hello,ssssssMethodHandle
hello,sssssMethodHandle
class org.zwc.methodhandletest.MHTest
class org.zwc.methodhandletest.MHTest
class org.zwc.methodhandletest.MHTest




Posted by MikeA on Sun, 03 May 2020 06:05:52 -0700