关于MethodHandle API的一些基本问题 [英] Some basic questions about MethodHandle API

查看:99
本文介绍了关于MethodHandle API的一些基本问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何通过 MethodHandles.lookup()获取所有声明的方法?我怎样才能获得所有声明的字段?

How can I obtain all declared method through MethodHandles.lookup()? How can I obtain all declared fields?

MethodHandle.invoke(),<$ c $之间有什么区别? c> MethodHandle.invokeExact()和 MethodHandle.invokeWithArguments()

此外,关于为 Java devloper 使用MethodHandle API的教程,我将不胜感激。我强调,我正在编写静态类型语言普通旧Java,我不是JVM开发人员,特别是我对整个字节码废话(invokedynamic)并不感兴趣。我想知道如何使用这个新API而不是Java Core API。

Also, I will be appreciate for tutorial about using MethodHandle API for Java devloper. I emphasize, I am programming on statically typed language plain old Java and I am not JVM developer, particularly I am not interesting with whole byte-code crap (invokedynamic). I want to figure out how can I use this new API instead of Java Core API.

EDITED-2:

@Glen最佳提供了一些参考文献的我想提供仅一个 http://www.oraclejavamagazine-digital.com/javamagazine/20130102?pg=52&search_term=methodhandle&doc_id=-1#pg50 这是正是我在寻找的东西。我发现实际上有一些新的词汇表。例如, target 实际上是指MethodHandle(而不是发送的对象)和调用站点实际上是代码调用函数指针又称MethodHandle。此外,必须了解MethodHandle API 不能替代 Core Reflection API而不是 suplement 。例如,您无法使用MethodHandle发现所有方法,而您需要Core Reflection API。但是当你找到你想要的方法时,你可以切换到MethodHandle,例如,绑定一些参数,或者将它的签名改变(改编)给varargs。

@Glen Best below provided some refferences I want to provide only one http://www.oraclejavamagazine-digital.com/javamagazine/20130102?pg=52&search_term=methodhandle&doc_id=-1#pg50 This is exactly what I was looking for. I figured out that actually there some new vocabalry.. For example, by target is actually meant MethodHandle (and not object to make dispatch upon) and call site is actually code that "invokes" "function pointer" aka MethodHandle. Also it is essential to understand that MethodHandle API is not replacement for Core Reflection API rather than suplement it. For example, you can't "discover" all methods with MethodHandle you need Core Reflection API. But when you "find" you desired method you can switch to MethodHandle and for example, bound some its parameters or "change" (adapt) it's signature to varargs for example.

已编辑:

我仍在努力找出答案。我写了一些我想和大家分享的测试。

I am still trying to figure out answer. I wrote some tests that I want to share with all.

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);
    }

}

推荐答案


如何通过MethodHandles.lookup()获取所有声明的方法?如何获取所有声明的字段?

将java.lang.invoke视为(快速执行)扩展到reflection(java.lang.reflect) - 即invoke类依赖于反射类。

Think of java.lang.invoke as a (fast performing) extension to reflection (java.lang.reflect) - i.e. "invoke" classes are dependent upon "reflection" classes.


  • 您获得参考通过反射到所有方法/构造函数/字段(java.lang.Class和java.lang.reflect):

  • You obtain reference to all methods/constructors/fields via reflection (java.lang.Class and java.lang.reflect):

java.lang.Class<?> someClass = ...;  // obtain a Class somehow

// Returns all constructors/methods/fields declared in class, 
// whether public/protected/package/private, 
// but does NOT include definitions from any ancestors:

java.lang.reflect.Constructor<?>[] declaredConstructors = someClass.getDeclaredConstructors();
java.lang.reflect.Method[] declaredMethods = someClass.getDeclaredMethods();
java.lang.reflect.Field[] declaredFields   = someClass.getDeclaredFields();

// Returns all constructors/methods/fields declared as public members 
// in the class AND all ancestors: 

java.lang.reflect.Constructor<?>[] publicInheritedConstructors = someClass.getConstructors();
java.lang.reflect.Method[] publicInheritedMethods = someClass.getMethods();
java.lang.reflect.Field[] publicInheritedFields   = someClass.getFields();


  • 您可以通过java.lang.invoke.MethodHandles.Lookup将它们转换为MethodHandles:

  • You convert them to MethodHandles via java.lang.invoke.MethodHandles.Lookup:

    java.lang.invoke.MethodType mt; 
    java.lang.invoke.MethodHandle mh;
    java.lang.invoke.MethodHandles.Lookup lookup = MethodHandles.lookup();
    
    // process methods
    for (java.lang.reflect.Method method: declaredMethods) {
        mh = lookup.unreflect(method);
    
        // can call mh.invokeExact (requiring first parameter to be the class' 
        // object instance upon which the method will be invoked, followed by 
        // the methodparameter types, with an exact match parameter and return 
        // types) or
        // mh.invoke/invokeWithArguments (requiring first parameter to be the 
        // class' object instance upon which the method will be invoked, 
        // followed by the method parameter types, with compatible conversions 
        // performed on input/output types)
    }
    
    // process constructors
    for (java.lang.reflect.Constructor<?> constructor: declaredConstructors) {
        mh = lookup.unreflectConstructor(constructor);
    
        // can call mh.invokeExact or
        // mh.invoke/invokeWithArguments 
    }
    
    // process field setters
    for (java.lang.reflect.Field field: declaredFields) {
        mh = lookup.unreflectSetter(field);
    
        // can call mh.invokeExact or
        // mh.invoke/invokeWithArguments 
    }
    
    // process field getters
    for (java.lang.reflect.Field field: declaredFields) {
        mh = lookup.unreflectGetter(field);
    
        // can call mh.invokeExact or
        // mh.invoke/invokeWithArguments 
    }
    


  • 您可以通过java.lang.reflect确定方法/构造函数/字段的签名:

  • You can determine if the signature of methods/constructors/fields via java.lang.reflect:

    // If generics involved in method signature:
    Type[] paramTypes = method.getGenericParameterTypes(); 
    Type returnType = method.getGenericReturnType(); 
    // Note: if Class is non-static inner class, first parameter of 
    // getGenericParameterTypes() is the enclosing class
    
    // If no generics involved in method signature:
    Class<?>[] paramTypes = declaredMethod.getParameterTypes(); 
    Class<?> returnType = declaredMethod.getReturnType(); 
    // Note: if Class is non-static inner class, first parameter of 
    // getParameterTypes() is the enclosing class
    
    // Same method calls for declaredConstructor
    


  • 您可以通过java.lang.reflect确定方法/构造函数/字段是否为静态:

  • You can determine if the methods/constructors/fields are static via java.lang.reflect:

    int modifiers = method.getModifiers();  // same method for constructor/field
    boolean isStatic = java.lang.Modifier.isStatic(modifiers);
    



  • 是什么区别betweeen MethodHandle.invoke(),MethodHandle.invokeExact()和MethodHandle.invokeWithArguments()?


    • 参见 http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/MethodHandle.html#invoke%28java.lang.Object...%29

    • 如果 MethodHandle 用于非静态方法,则提供给这些方法的第一个参数是声明方法的 Class 。在该类的实例上调用该方法(或者在静态方法的类本身上调用)。如果 Class 是非静态内部类,则第二个参数是封闭/声明类的实例。后续参数是方法签名参数,按顺序排列。

    • invokeExact 不执行自动兼容类型转换输入参数。它要求参数值(或参数表达式)与方法签名完全匹配,每个参数作为单独的参数提供或者所有参数作为数组一起提供(签名: Object invokeExact(Object。 .. args))。

    • 调用 要求参数值(或参数表达式)与方法签名类型兼容 - 执行自动类型转换,每个参数作为单独的参数提供或者所有参数作为数组一起提供(签名:对象调用(对象... args))

    • invokeWithArguments 要求参数值(或参数表达式)与方法签名类型兼容 - 执行自动类型转换,每个参数在List中提供(签名: Object invokeWithArguments(List<?> arguments)

    • see http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/MethodHandle.html#invoke%28java.lang.Object...%29
    • If the MethodHandle is for a non-static method, the first parameter provided to these methods is an instance of the Class which declares the method. The method is invoked on this instance of the class (or on the Class itself for static methods). If the Class is a non-static inner class, the second parameter is an instance of the enclosing/declaring class. The subsequent parameters are the method signature parameters, in order.
    • invokeExact does not do automatic compatible type conversion on input parameters. It requires parameter values (or parameter expressions) to be an exact type match to the method signature, with each parameter provided as a separate argument OR all arguments provided together as an array (signature: Object invokeExact(Object... args)).
    • invoke requires the parameter values (or parameter expressions) to be type compatible match to the method signature - automatic type conversions are performed, with each parameter provided as a separate argument OR all arguments provided together as an array (signature: Object invoke(Object... args))
    • invokeWithArguments requires the parameter values (or parameter expressions) to be type compatible match to the method signature - automatic type conversions are performed, with each parameter provided within a List (signature: Object invokeWithArguments(List<?> arguments))

    • 我将非常感谢您使用MethodHandle API for Java devloper

      不幸的是,那里并不多。您可以尝试以下方法。希望我已经给出了足够的信息:^)

      There's not much out there, unfortunately. You could try the following. Hopefully, I've given enough info above :^)

      http://docs.oracle.com/javase/7/docs/api/java/lang/invoke/MethodHandle.html

      http:// docs .oracle.com / javase / 7 / docs / api / java / lang / invoke / MethodHandles.Lookup.html

      http://www.java7developer.com/blog/?p=191

      http://www.oraclejavamagazine-digital.com/javamagazine/20130102?pg= 52& search_term = methodhandle& doc_id = -1#pg50

      http://www.amazon.com/Well-Grounded-Java-Deve loper-techniques-programming / dp / 1617290068

      这篇关于关于MethodHandle API的一些基本问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆