516. Java 方法句柄 - 转换(进阶篇·下)

516. Java 方法句柄 - 转换(进阶篇·下)

除了 插入参数过滤参数MethodHandles 还支持更高级的组合方式:

  • 参数折叠(foldArguments)
  • 返回值过滤(filterReturnValue)

这两个操作让我们能在调用目标方法前后,加上一层"预处理"和"后处理"。


1. 参数折叠:foldArguments

💡 场景

当我们想在目标方法执行前,先对部分参数做运算,并把结果作为新的参数插入,就可以用 foldArguments

这相当于在方法调用前,插入一个"小计算工厂"。


示例:先计算再传递

目标方法:

java 复制代码
private static void target(int sum, int a, int b, int ignored) {
    System.out.printf("%d + %d equals %d and %d is ignored%n", a, b, sum, ignored);
}

其中:

  • ignored 用来展示占位(和折叠逻辑无关);
  • sum 参数要由 a + b 计算得到;
  • ab 是原始输入。

现在写一个组合器方法:

java 复制代码
private static int sum(int a, int b) {
    return a + b;
}

组合步骤:

java 复制代码
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle targetMH = lookup.findStatic(
    Example.class,
    "target",
    MethodType.methodType(void.class, int.class, int.class, int.class, int.class));

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

MethodHandle folded = MethodHandles.foldArguments(targetMH, sumMH);

解释:

  • targetMH:目标方法。
  • sumMH:预处理(组合器)方法。
  • 1sum 参数的位置,代表折叠结果插入的地方。

调用:

java 复制代码
folded.invokeExact(1, 2, 10000); // a=1, b=2, ignored=10000
// 输出: "1 + 2 equals 3 and 10000 is ignored"

👉 我们只传了 (ignored=10000, a=1, b=2)sum 自动由 a+b=3 计算并插入。


📌 补充:

  • 如果组合器方法没有返回值,它也能执行副作用,此时目标方法无需保留 sum 这样的占位参数。
  • 适合 日志记录、参数校验、动态计算默认值 等场景。

2. 返回值过滤:filterReturnValue

💡 场景

有时候我们希望对目标方法的返回值再做一次处理。 比如:字符串后处理、结果校正、格式转换。

这时可以用 filterReturnValue


示例:结果加工

目标方法:

java 复制代码
private static String getSomeString() {
    return "dummy";
}

转换方法:

java 复制代码
private static String resultTransform(String value) {
    return value.replace('d', 'm').toUpperCase();
}

组合:

java 复制代码
MethodHandle getSomeStringMH = lookup.findStatic(
        Example.class, "getSomeString", MethodType.methodType(String.class));

MethodHandle resultTransformMH = lookup.findStatic(
        Example.class, "resultTransform", MethodType.methodType(String.class, String.class));

MethodHandle filtered = MethodHandles.filterReturnValue(getSomeStringMH, resultTransformMH);

System.out.println(filtered.invoke()); 
// 输出: "MUMMY"

👉 运行过程:

  1. 调用 getSomeString()"dummy"
  2. 结果传递给 resultTransform()"mummy""MUMMY"

🎯 总结

  • foldArguments :先处理一部分参数,把结果"折叠"进目标方法。
    • 类比:进餐厅点菜时,服务员会先把"人数统计好",再填入账单。
  • filterReturnValue :对目标方法的返回值做后处理。
    • 类比:打印机先打印(目标方法),然后加个"塑封膜"(返回值加工)。
相关推荐
妙码生花1 小时前
全网 8k star 的 BuildAdmin 正式发布 Golang 版本,这次我们在CRUD赛道杀死了比赛。
前端·后端·ai编程
Zane19941 小时前
复制算法明明要浪费一半内存,为什么新生代还偏偏用它
java·后端
写代码像蔡徐抻1 小时前
三年了,AI为何还没有抢走程序员饭碗?
前端·后端·面试
魔兽大山哥1 小时前
【NL2SQL 实战 08】主链路:从提问到出数,图里跑了哪些节点
后端
Zane19941 小时前
只重写了 __eq__,为什么类突然变得不可哈希了?常用魔法方法大盘点
后端·python
程序员cxuan1 小时前
Claude Fable 5.1 的提示词又被扒了
人工智能·后端·程序员
梦曦i1 小时前
unix-router v0.1.0 首发:uni-app x 的 vue-router 风格路由库
前端·uni-app
步行cgn1 小时前
Spring Boot 绑定简单 Bean 详解
java·spring boot·后端
Linsk1 小时前
妙用:focus解决0到auto高度过渡的边界场景
前端·css