MethodHandles

MethodHandles侧重于调用某个方法的本身, 提供了一种更高效和更底层的方法调用机制; 它和传统的反射是互补的, 合理搭配使用能使代码更加灵活高效

调用方法的例子:

一个私有方法和一个公共方法和一个私有属性

package com.example.temp.methods;

public class MethodsOne {

	private String name;

    private boolean compare1(String a, String b) {
        return a.equals(b);
    }

    public boolean compare2(int a, int b) {
        return a > b;
    }
}

在Test里使用MethodHandles分别调用以上两个方法和对私有属性的设值与获取

package com.example.temp;

import com.example.temp.methods.MethodsOne;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.lang.invoke.*;
import java.util.*;

@SpringBootTest
class TempApplicationTests {

    @Test
	void invokePrivateMethod() throws Throwable {
	    //用来获取访问private或protected方法的Lookup对象
		//也可以访问public方法(不推荐), 但需要额外的权限检查开销, 同时也会让代码意图不清晰,暗示需要特殊权限
		MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(MethodsOne.class, MethodHandles.lookup());
		//findVirtual可用于查找实例方法(public | protected | private)
		MethodHandle virtual = lookup.findVirtual(
				//目标类
				MethodsOne.class,
				//方法名字
				"compare1",
				//方法签名: 返回值类型, 参数1类型, 参数2类型
				MethodType.methodType(boolean.class, String.class, String.class)
		).bindTo(new MethodsOne());//绑定方法所在的实例
		boolean result = (boolean)virtual.invokeExact("a", "a");//调用和入参
		System.out.println(result); //true
    }


    @Test
	void invokePublicMethod() throws Throwable {
		//用来获取访问public方法的Lookup对象
		MethodHandles.Lookup lookup = MethodHandles.lookup();
		//findVirtual可用于查找实例方法(public | protected | private)
		MethodHandle virtual = lookup.findVirtual(
				//目标类
				MethodsOne.class,
				//方法名字
				"compare2",
				//方法签名: 返回值类型, 参数1类型, 参数2类型
				MethodType.methodType(boolean.class, int.class, int.class)
		).bindTo(new MethodsOne());//绑定方法所在的实例
		boolean result = (boolean) virtual.invokeExact(20, 10);//调用和入参
		System.out.println(result); //true
	}


    @Test
	void nameFieldSetterAndGetter() throws Throwable {
		MethodsOne methodsOne= new MethodsOne();
		MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(MethodsOne.class, MethodHandles.lookup());
		MethodHandle set = lookup.findSetter(
						MethodsOne.class,
						"name",
						String.class
		).bindTo(methodsOne);
		set.invoke("a");//设置name的值为a
		
		MethodHandle get = lookup.findGetter(
						MethodsOne.class,
						"name",
						String.class
		).bindTo(methodsOne);
		String value = (String) get.invoke();
		System.out.println(value);//a
	}
}

==============================================================================

Function简单使用

package com.example.temp.methods;

import java.util.function.Function;

public class MethodTwo {

    private String scoreScope(int score, Function<Integer, String> function) {
        return function.apply(score);
    }
}
package com.example.temp;

import com.example.temp.methods.MethodTwo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.lang.invoke.*;
import java.util.*;
import java.util.function.Function;

@SpringBootTest
class TempApplicationTests {

	@Test
	void funcationCase() throws Throwable {
		Function<Integer, String> compare = x -> x >= 90 ? "A" : (x >= 80) ? "B" : (x >= 70) ? "C" : (x >= 60) ? "D" : "E";
		MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(MethodTwo.class, MethodHandles.lookup());
		MethodHandle virtual = lookup.findVirtual(
				MethodTwo.class,
				"scoreScope",
				MethodType.methodType(String.class, int.class, Function.class)
		).bindTo(new MethodTwo());
		String result = (String)virtual.invokeExact(75, compare);
		System.out.println(result);//c
	}
	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值