515. Java 方法句柄 - 转换 (进阶篇)

515. Java 方法句柄 - 转换 (进阶篇)

除了前面学到的 asType 类型适配和 permuteArguments 参数重排,
MethodHandles 还提供了更强大的 参数插入参数过滤 功能。

这让我们能够像“拼装积木”一样,对方法句柄进行再加工。


1. 插入参数(insertArguments

有时我们调用方法时,某些参数总是固定的。
与其每次都手动传入,不如把它们提前绑定在 MethodHandle 里。

这就是 insertArguments 的作用:
👉 它允许我们预先绑定一个或多个参数,从而得到一个新的 MethodHandle

示例:预绑定参数

假设有这样的方法:

public static void test(int v1, String v2, long v3, boolean v4) {
    System.out.println(v1 + v2 + v3 + v4);
}

找到方法句柄:

MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle target = lookup.findStatic(
        Example.class,
        "test",
        MethodType.methodType(void.class, int.class, String.class, long.class, boolean.class));

我们希望每次调用时,Stringlong 参数总是 "new"3L
那么可以这样绑定:

MethodHandle bound = MethodHandles.insertArguments(target, 1, "new", 3L);

这里的 1 表示:从第二个参数位置开始绑定。

调用时就只需要传入剩下的参数了:

bound.invoke(1, true); 
// 输出: "1new3true"

⚠️ 注意:
如果你再传入已经预绑定的参数,会抛出 WrongMethodTypeException


2. 过滤参数(filterArguments

有时我们希望在调用目标方法前,对某些参数做预处理
这时可以用 filterArguments

使用方法

filterArguments 需要三个要素:

  1. 目标方法句柄(最终被调用的方法)。
  2. 开始过滤的参数索引
  3. 一组“过滤器方法句柄”,它们会依次处理指定的参数。

如果某些参数不需要处理,可以传入 null
甚至可以只处理一部分参数,剩下的保持原样。


示例:参数变换

还是使用刚才的 test 方法。
我们准备两个“过滤器”:

private static boolean negate(boolean original) {
    return !original;
}

private static int increment(int original) {
    return ++original;
}

分别用于 布尔取反整数自增

获取它们的方法句柄:

MethodHandle negate = lookup.findStatic(
        Example.class, "negate", MethodType.methodType(boolean.class, boolean.class));

MethodHandle increment = lookup.findStatic(
        Example.class, "increment", MethodType.methodType(int.class, int.class));

现在组合:

MethodHandle withFilters = MethodHandles.filterArguments(
        target, 0, increment, null, null, negate);

解释一下:

  • 0 表示从第一个参数开始过滤。
  • 第一个参数(int v1) → 用 increment 过滤。
  • 第二个和第三个参数(String, long) → 不变(传 null)。
  • 第四个参数(boolean v4) → 用 negate 过滤。

调用:

withFilters.invoke(3, "abc", 5L, false);
// 输出: "4abc5true"

👉 我们传入 (3, "abc", 5L, false)
在进入 test 方法前变成了 (4, "abc", 5L, true)


🎯 总结

  • insertArguments:提前绑定部分参数,适合“固定上下文”。
    • 类比:在点外卖时,你把“饮料=可乐”“辣度=中辣”写死,下次只选主菜。
  • filterArguments:对传入参数做预处理,适合“数据校正/转换”。
    • 类比:进入工厂流水线前,先把原材料“切一刀”“翻转一下”,再进入主流程。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容