MethodHandle详解 基础应用

文章展示了如何使用Java的MethodHandle进行构造器调用、方法调用(包括私有方法)、静态方法调用以及属性访问。通过创建HandleTarget类和HandleTargetTest测试类,演示了MethodHandle在动态方法调用中的灵活性。
摘要由CSDN通过智能技术生成

基类

package methodhandle;

/**
 * HandleTarget
 *
 * @author yuan_kf
 * @version 1.0
 * @date 2023/4/10 09:46
 * @description
 */
public class HandleTarget {

    public String name = "hello world";

    public HandleTarget() {
    }

    public HandleTarget(String name) {
        this.name = name;
    }

    public void connectName(String name) {
        this.name = this.name + " " + name;
    }

    public String getName() {
        return name;
    }

    private void learnPrograming(String lang) {
        System.out.println(String.format("I am learning %s ", lang));
    }

    public static String declaration(String author) {
        return author + ": " + "吾生也有涯,而知也无涯。以有涯随无涯,殆己";
    }

    @Override
    public String toString() {
        return "HandleTarget{" +
                "name='" + name + '\'' +
                '}';
    }
}


测试类

package methodhandle;

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;

/**
 * HandleTargetTest
 *
 * @author yuan_kf
 * @version 1.0
 * @date 2023/4/10 09:47
 * @description
 */
public class HandleTargetTest {


    public static void main(String[] args) throws Throwable {

        MethodHandles.Lookup lookup = MethodHandles.lookup();

//        MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();

        System.out.println("---无参数构造---");
        //无参数构造器
        MethodType con1Mt = MethodType.methodType(void.class);
        MethodHandle constructor = lookup.findConstructor(HandleTarget.class, con1Mt);
        Object target1 = constructor.invoke();
        System.out.println(target1);


        System.out.println("---有参数构造--");
        // 有参数构造; 第一个是返回值,第二个是参数
        MethodType methodType = MethodType.methodType(void.class, String.class);
        MethodHandle constructor1 = lookup.findConstructor(HandleTarget.class, methodType);
        Object target2 = constructor1.invoke("toDay");
        System.out.println(target2);



        System.out.println("---访问非private实例方法---");
        MethodType getterMt = MethodType.methodType(String.class);
        MethodHandle getName = lookup.findVirtual(HandleTarget.class, "getName", getterMt);
        String name = (String) getName.invoke(target2);
        System.out.println(name);



        System.out.println("---访问private实例方法---");
        //访问private方法
        Method learnMethod = HandleTarget.class.getDeclaredMethod("learnPrograming", String.class);
        learnMethod.setAccessible(true);
        MethodHandle learnProMh = lookup.unreflect(learnMethod);
        // 需要一个无参构造函数去访问,类似 先new一个无参构造、在执行私有化方法
        learnProMh.invoke(target1, "Java");


        System.out.println("---访问非private 静态方法---");
        MethodType methodType1 = MethodType.methodType(String.class, String.class);
        MethodHandle declaration = lookup.findStatic(HandleTarget.class, "declaration", methodType1);
        Object zuanzi = declaration.invoke("钻子");
        System.out.println(zuanzi);


        System.out.println("---访问 getter 方法---, 私有属性必须是public修饰");
//        MethodHandle getter = lookup.findGetter(HandleTarget.class, "name", String.class);
//        Object getterInvoke = getter.invoke(constructor);
//        System.out.println(getterInvoke);


        System.out.println("---访问private属性---");
        //访问private的属性,需要借助反射
        Field nameField = HandleTarget.class.getDeclaredField("name");
        nameField.setAccessible(true);
        MethodHandle nameFromRefMh = lookup.unreflectGetter(nameField);
        System.out.println((String) nameFromRefMh.invoke(target1));


        System.out.println("---增强MethodHandle---");
        // 当我们创建了"connectName"方法的MethodHandle,可以不立即调用而是将其绑定到某个对象上,
        // 这个对象的类型必须是HandleTarget及其子类,那么调用重新获得MethodHandle时,其会调用到新绑定对象里面的那个方法上。
        MethodType methodType2 = MethodType.methodType(void.class, String.class);  // 定义函数返回

        MethodHandle setterMh = lookup.findVirtual(HandleTarget.class, "connectName", methodType2);
        MethodHandle bindedSetterMh = setterMh.bindTo(target2); // 绑定到另一个对对象上去;
        bindedSetterMh.invoke("love love "); // 赋值
        System.out.println((String) getName.invoke(target2)); // 输出

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值