关于 MethodHandle API 的一些基本问题
如何通过以下方式获取所有声明的方法?如何获取所有声明的字段?MethodHandles.lookup()
和MethodHandle.invoke()MethodHandle.invokeExact()MethodHandle.invokeWithArguments()
另外,我将不胜感激有关使用MethodHandle API for Java devloper的教程。我强调,我正在用静态类型语言编程,普通的旧Java,我不是JVM开发人员,特别是我对整个字节码废话(invokedynamic)不感兴趣。我想弄清楚如何使用这个新的API而不是Java Core API。
已编辑-2:
@Glen下面的最佳提供了一些参考,我只想提供一个 http://www.oraclejavamagazine-digital.com/javamagazine/20130102?pg=52&search_term=methodhandle&doc_id=-1#pg50 这正是我一直在寻找的。我发现实际上有一些新的vocabary.例如,按目标实际上意味着方法处理(而不是进行调度的对象),而调用站点实际上是“调用”“函数指针”(即MethodHandle)的代码。此外,还必须了解MethodHandle API不能取代Core Reflection API,而是取代它。例如,您无法使用方法处理“发现”所有方法,您需要核心反射API。但是当你“找到”你想要的方法时,你可以切换到MethodHandle,例如,绑定它的一些参数或“更改”(适应)它的签名到varargs。
编辑:
我仍然在试图找出答案。我写了一些测试,我想与所有人分享。
package alexander.berkovich;
import static org.junit.Assert.assertSame;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.junit.BeforeClass;
import org.junit.Test;
public class MethodHandlerCleanTest {
    public static MethodHandles.Lookup lookup;
    @BeforeClass
    public static void asetUp(){
        lookup = MethodHandles.lookup();
    }
    public static class Check {
        public void primitive(final int i){
        }
        public void wrapper(final Integer i){
        }
    }
    @Test
    public void testPrimitive() throws Throwable {
        Check check = new Check();
        MethodType type = MethodType.methodType(void.class, int.class);
        MethodHandle mh = lookup.findVirtual(Check.class, "primitive", type);
        mh.invokeWithArguments(check, 1);
        mh.invoke(check, (short)2);
        mh.invoke(check, Integer.valueOf(3));
        Method method = Check.class.getMethod("primitive", int.class);
        method.invoke(check, (short)20);
        method.invoke(check, Integer.valueOf(21));
    }
    @Test
    public void testWrapper() throws Throwable {
        Check check = new Check();
        MethodType type = MethodType.methodType(void.class, Integer.class);
        MethodHandle mh = lookup.findVirtual(Check.class, "wrapper", type);
        mh.invoke(check, 2);
        Method method = Check.class.getMethod("wrapper", Integer.class);
        method.invoke(check, 20);
    }
    @SuppressWarnings("unused")
    public static class StaticInnerClass {
        public static String staticName;
        public String name;
        public void foo(){}
        public static void staticFoo(){}
    }
    @Test
    public void testStaticInnerClassStaticField() throws Throwable {
        MethodHandle mhSet = lookup.findStaticSetter(StaticInnerClass.class, "staticName", String.class);
        String expected = "mama";
        mhSet.invoke(expected);
        MethodHandle mhGet = lookup.findStaticGetter(StaticInnerClass.class, "staticName", String.class);
        Object obj = mhGet.invoke();
        String value = (String)obj;
        assertSame(expected, value);
    }
    @Test
    public void testStaticInnerClassField() throws Throwable {
        StaticInnerClass sut = new StaticInnerClass();
        Field f = StaticInnerClass.class.getDeclaredField("name");
        MethodHandle mhSetUnreflect = lookup.unreflectSetter(f); 
        String expectedUnreflect = "unreflect";
        mhSetUnreflect.invoke(sut, expectedUnreflect);
        MethodHandle mhSet = lookup.findSetter(StaticInnerClass.class, "name", String.class);
        String expected = "mama";
        mhSet.invoke(sut, expected);
        MethodHandle mhGet = lookup.findGetter(StaticInnerClass.class, "name", String.class);
        Object obj = mhGet.invoke(sut);
        String value = (String)obj;
        assertSame(expected, value);
    }
    @Test
    public void testStaticInnerClassConstructor() throws Throwable {
        StaticInnerClass sut = new StaticInnerClass();
        MethodType type = MethodType.methodType(void.class);
        MethodHandle mh = lookup.findConstructor(StaticInnerClass.class, type);
        mh.invoke();
    }
    @Test
    public void testStaticInnerClassMethod() throws Throwable {
        StaticInnerClass sut = new StaticInnerClass();
        MethodType type = MethodType.methodType(void.class);
        MethodHandle mh = lookup.findVirtual(StaticInnerClass.class, "foo", type);
        mh.invoke(sut);
    }
    @Test
    public void testStaticInnerClassStaticMethod() throws Throwable {
        MethodType type = MethodType.methodType(void.class);
        MethodHandle mh = lookup.findStatic(StaticInnerClass.class, "staticFoo", type);
        mh.invoke();
    }
    @SuppressWarnings("unused")
    private class InnerClass {
        public String name;
        public void foo(){}
    }
    @Test
    public void testInnerClassField() throws Throwable {
        InnerClass sut = new InnerClass();
        MethodHandle mhSet = lookup.findSetter(InnerClass.class, "name", String.class);
        String expected = "mama";
        mhSet.invoke(sut, expected);
        MethodHandle mhGet = lookup.findGetter(InnerClass.class, "name", String.class);
        Object obj = mhGet.invoke(sut);
        String value = (String)obj;
        assertSame(expected, value);
    }
    @Test
    public void testInnerClassConstructor() throws Throwable {
        MethodType type = MethodType.methodType(void.class, MethodHandlerCleanTest.class);
        //default constructor is private
        Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
        field.setAccessible(true);
        MethodHandles.Lookup trustedLookup = (MethodHandles.Lookup) 
                field
                .get(null);
        MethodHandle mh = trustedLookup.findConstructor(InnerClass.class, type);
        mh.invoke(this);
    }
    @Test
    public void testInnerClassMethod() throws Throwable {
        InnerClass sut = new InnerClass();
        MethodType type = MethodType.methodType(void.class);
        MethodHandle mh = lookup.findVirtual(InnerClass.class, "foo", type);
        mh.invoke(sut);
    }
}