package com.haogrgr.test.main; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; public class MethodHandleTest { static class ClassA { public void println(String s) { System.out.println(s); } } public static void main(String[] args) throws Throwable { Object obj = System.currentTimeMillis() % 2 == 0 ? System.out : new ClassA(); // 无论obj最终是哪个实现类,下面这句都能正确调用到println方法。 MethodHandle printlnMH = getPrintlnMH(obj); printlnMH.invokeExact("icyfenix"); printlnMH.invokeExact("icyfenix"); printlnMH.invokeExact("icyfenix"); printlnMH.invokeExact("icyfenix"); printlnMH.invokeExact("icyfenix"); printlnMH.invokeExact("icyfenix"); } private static MethodHandle getPrintlnMH(Object reveiver) throws Throwable { // MethodType:代表“方法类型”,包含了方法的返回值(methodType()的第一个参数)和具体参数(methodType()第二个及以后的参数)。 MethodType mt = MethodType.methodType(void.class, String.class); // lookup()方法来自于MethodHandles.lookup,这句的作用是在指定类中查找符合给定的方法名称、方法类型,并且符合调用权限的方法句柄。 // 因为这里调用的是一个虚方法,按照Java语言的规则,方法第一个参数是隐式的,代表该方法的接收者,也即是this指向的对象,这个参数以前是放在参数列表中进行传递,现在提供了bindTo()方法来完成这件事情。 Lookup lookup = MethodHandles.lookup(); MethodHandle findVirtual = lookup.findVirtual(reveiver.getClass(), "println", mt); MethodHandle bindTo = findVirtual.bindTo(reveiver); return bindTo; } }