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 :对目标方法的返回值做后处理。
    • 类比:打印机先打印(目标方法),然后加个"塑封膜"(返回值加工)。
相关推荐
定栓14 分钟前
Webpack迁到Vite第七节(一):全家桶移除 — 配置文件与构建核心
前端·webpack·node.js
码艺-Alimjan21 分钟前
维吾尔语 RTL 排版的隐形利器:`\u200F`
前端·javascript
alwaysrun21 分钟前
Web之wasm-pack详解
前端·rust·web·wasm
许雪里29 分钟前
Agent 记忆架构设计:原理 × 业界三大范式 × XXL-AI 落地实践
后端·llm·agent
广州华水科技1 小时前
如何通过单北斗GNSS实现精准的变形监测?
前端
云和数据.ChenGuang1 小时前
print(f“a+b=“,result) print(f“a+b={result}“)区别
java·前端·人工智能·python·深度学习
速易达网络2 小时前
基于 Vue3 + Flask + ECharts 构建政务 OA 系统门户
前端·echarts·政务
何何____2 小时前
TypeScript 函数类型兼容性
前端·javascript·typescript
雪芽蓝域zzs2 小时前
json数据转化成interface属性
前端·javascript·json