Java方法句柄 MethodHandle介绍

MethodHandle是干什么用的

说到反射大家肯定都很清楚,但是不一定知道MethodHandle。那么MethodHandle是干啥的?MethodHandle实现了Java反射的大部分功能,但它实际上是一种函数指针,非常类似于C++的函数指针。 有的文章称之为“现代化反射”。其实它和反射还是有很大的差别的。

  • 从本质上讲,反射是模拟Java代码层次级别的调用,而MethodHandle是模拟字节码层次级别调用。
  • 反射中Method对象包含的信息要比MethodHandle包含的信息多,包含了方法的签名,描述符以及方法属性表中各种属性的Java端表达方式,以及执行全线等信息。
  • MethodHandle是针对字节码级别的应用,所以它是针对所有的JVM语言的,而反射仅仅是Java语言级别的应用。

MethodHandle有什么应用

反射

和反射一样,但是比反射效率要高,因为直接是操作字节嘛。另外他是内联的,效率更高。

支持动态语言

我们知道JVM的发展方向是支持动态语言的,在JAVA 8中就已经支持了lambda表达式。还有一些其他的动态jvm语言,比如最近很火热的Kotlin。JVM中使用
invokedynamic这条新的指令。

MethodHandle使用例子

如何使用,先看步骤

1,获取MethodType对象。

  //第一个参数是返回值的类型,后面的参数是方法的参数类型。
    MethodType m=MethodType.methodType(....);

2,获取Looup对象。

   MethodHandles.Lookup lookup = MethodHandles.lookup();

3,获取MethodHandle对象

MethodHandle methodHandle = lookup.findVirtual(MHTest.class,"toString",mt);

4,调用方法

    String s = (String) methodHandle.invokeExact(test,"nihao");

上述步骤,大家一定要记住,有了步骤。就按照步骤来写个例子吧。

package com.nanguiyu;


public class MethodTest {


   public String mh(String str){
       return str;
   }



}


package com.nanguiyu;

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

public class Test {
    public static void main(String[] args){
        MethodType mt = MethodType.methodType(String.class,String.class);
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        try {
            MethodTest methodTest = new MethodTest();
            MethodHandle methodHandle = lookup.findVirtual(MethodTest.class,"mh",mt);
            String message = (String) methodHandle.invoke(methodTest,"Hello,World");
            System.out.println(message);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}

MethodHandle 不能访问私有方法,是一个轻量级的反射。另外还必须获取到要反射类的对象。说到这里,大家是不是觉得有点奇怪。
获取了对象的实例,还反射啥,直接调用不就行了吗?那我们就先反射得到对象,然后在反射方法。

package com.nanguiyu;

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

public class Test {
    public static void main(String[] args){
        MethodType mt = MethodType.methodType(String.class,String.class);
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        try {
            MethodType methodType = MethodType.methodType(void.class);
            MethodHandle methodTest = lookup.findConstructor(MethodTest.class,methodType);
            MethodTest m = (MethodTest) methodTest.invoke();
            MethodHandle methodHandle = lookup.findVirtual(MethodTest.class,"mh",mt);
            String message = (String) methodHandle.invoke(m,"Hello,World");
            System.out.println(message);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }
}

大功告成了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值