zoukankan      html  css  js  c++  java
  • Java的动态性支持学习六 方法句柄 获取和调用

    Java的动态性支持学习一 - 反射机制 概念概述
    Java的动态性支持学习二 - 反射机制 属性、方法、对象的操作
    Java的动态性支持学习三 - 反射机制 取消属性、方法、构造器的访问限制
    Java的动态性支持学习四 - 反射调用的性能对比
    Java的动态性支持学习五 - 方法句柄 概念和句柄类型
    Java的动态性支持学习六 - 方法句柄 获取和调用
    Java的动态性支持学习七 - 方法句柄调用的性能对比

    获取方法句柄

    获取方法句柄和反射API类型,从已有的类中根据一定的条件进行查找,但与反射不同的是方法句柄部分构造器、方法和字段,而是统一转换成MethodHandle对象。对于字段类说,获取到的是用来获取和设置该字段值的方法句柄。

    方法句柄的查找是通过 java.lang.invoke.MethodHandles.Lookup类来完成的。首先调用MethodHandles.lookup方法获取MethodHandles.Lookup对象,.MethodHandles.Lookup类提供了一些方法根据不同的条件进行查找:

    //分别是字段Get和Set方法句柄,第一个参数为类的class对象,第二个参数为字段名,第三个参数为字段数据类型;
    lookup.findGetter(C.class,"f",FT.class)
    lookup.findSetter(C.class,"f",FT.class)
    //分别是静态字段Get和Set方法句柄,第一个参数为类的class对象,第二个参数为字段名,第三个参数为字段数据类型;
    lookup.findStaticGetter(C.class,"f",FT.class)
    lookup.findStaticSetter(C.class,"f",FT.class)
    //分别是一般方法和静态方法的方法句柄,第一个参数为类的class对象,第二个参数为方法名,第三个参数为MethodType对象;
    lookup.findVirtual(C.class,"m",MT)
    lookup.findStatic(C.class,"m",MT)
    //构造器的方法句柄,第一个参数为类的class对象,第二个为MethodType对象;
    lookup.findConstructor(C.class,MT)
    //查找类中的特殊方法,主要是类中的私有方法。
    lookup.findSpecial(C.class,"m",MT,this.class)

    其中findSpecial方法比之前的findVirtual和findStatic等方法多了一个参数。这个额外的参数用来指定私有方法被调用时所使用的类。提供这个类的原因是为了满足对私有方法的访问控制的要求。当方法句柄被调用时,指定的调用类必须具备访问私有方法的权限,否则会出现无法访问的错误。

    除了直接在某个类中进行查找之外,还可以从通过反射API得到的Constructor、Field和Method等对象中获得方法句柄。如代码清单2-47所示,首先通过反射API得到表示构造方法的Constructor对象,再通过unreflectConstructor方法就可以得到其对应的一个方法句柄;而通过unreflect方法可以将Method类对象转换成方法句柄。对于私有方法,则需要使用unreflectSpecial来进行转换,同样也需要提供一个作用与findSpecial中参数相同的额外参数;对于Field类的对象来说,通过unreflectGetter和unreflectSetter就可以得到获取和设置其值的方法句柄。请读者自行学习。

    方法句柄的调用

    在获取一个方法句柄后,最直接的使用方法就是调用它所引用的底层方法。比较常用的方法是invokeExact:

    Object	invokeExact(Object... args)
    

    invokeExact的参数是可变的,参数一次是作为方法接受者的对象和调用时候的实际参数列表。但如果是静态方法,则不要指定接收对象,参数都是实际参数列表。

    Demo如下:
    package net.oseye;
    import java.lang.invoke.MethodHandle;
    import java.lang.invoke.MethodHandles;
    import java.lang.invoke.MethodType;
    
    public class ReflectTest {
    	
    	public static void main(String[] args) throws Throwable{ 
    		User user=new User("kevin");
    		MethodHandles.Lookup lookkup=MethodHandles.lookup();
    		MethodHandle mth=lookkup.findVirtual(User.class, "SayHello", MethodType.methodType(void.class,String.class));
    		mth.invokeExact(user,"oseye");
    	}
    }
    class User{
    	private String name;
    	public User(String name){this.name=name;}
    	public void SayHello(String name){
    		System.out.println(this.name+" Say Hello,"+name);
    	}
    }
  • 相关阅读:
    BZOJ 1057 悬线法求最大01矩阵
    POJ 2248
    SPOJ
    51NOD
    2017-2018 ACM-ICPC, NEERC, Moscow Subregional Contest J. Judging the Trick
    POJ 1379 模拟退火
    POJ 2420 模拟退火
    Frontend 事后诸葛亮
    【Frontend】Alpha Review 展示博客
    ASE19 团队项目 alpha 阶段 Frontend 组 scrum5 记录
  • 原文地址:https://www.cnblogs.com/zhaiqianfeng/p/4618328.html
Copyright © 2011-2022 走看看