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"
👉 运行过程:
- 调用
getSomeString()→"dummy" - 结果传递给
resultTransform()→"mummy"→"MUMMY"
🎯 总结
foldArguments:先处理一部分参数,把结果"折叠"进目标方法。- 类比:进餐厅点菜时,服务员会先把"人数统计好",再填入账单。
filterReturnValue:对目标方法的返回值做后处理。- 类比:打印机先打印(目标方法),然后加个"塑封膜"(返回值加工)。