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 计算得到;
  • a 和 b 是原始输入。

现在写一个组合器方法:

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:预处理(组合器)方法。
  • 1:sum 参数的位置,代表折叠结果插入的地方。

调用:

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 :对目标方法的返回值做后处理。
    • 类比:打印机先打印(目标方法),然后加个"塑封膜"(返回值加工)。
相关推荐
子兮曰5 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰5 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
前端小万5 天前
写公众号赚了 3000 块后,我做了一款叫 "一键成稿" 的软件
前端·微信小程序
爱勇宝5 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
胡写代码5 天前
别再前后端各写一套表单校验了
java·后端
三十而立洋5 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
大勇前进5 天前
原生 PHP 还是 Laravel?小项目到底要不要上框架
后端
yuzhi_liu5 天前
我用 LangGraph4j 实现 Multi-Agent Supervisor
后端
alsmile5 天前
Node-RED 之外,国产规则引擎的新方案:基于标准语法,Go 先行实现
后端·开源·go
大白805 天前
PHP 内存溢出排查思路:看懂报错日志,精准定位问题
后端