如何创建无参MethodHandle:每次调用两次执行randomIntProvider并传参给intConcatenator
解决方案:创建无参MethodHandle,每次调用触发两次随机数生成
当然可以实现这个需求!你之前碰到的问题,本质是因为错误地提前计算了randomIntProvider的结果并绑定成了常量参数——而我们需要的是让每次调用最终的MethodHandle时,都重新触发两次randomIntProvider的调用,再把结果传给intConcatenator。
核心思路
关键在于直接绑定randomIntProvider这个MethodHandle本身,而非它的计算结果。利用Java的MethodHandles工具类提供的insertArguments和foldArguments方法,我们可以把两次随机数生成的逻辑嵌入到最终的无参MethodHandle中,确保每次调用都重新执行随机数生成。
代码示例
假设我们的两个MethodHandle定义如下(先模拟实现方便测试):
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Random; public class MethodHandleDemo { public static void main(String[] args) throws Throwable { // 模拟randomIntProvider:无参,返回随机int MethodHandle randomIntProvider = MethodHandles.lookup() .findStatic(Random.class, "nextInt", MethodType.methodType(int.class)); // 模拟intConcatenator:接收两个int,返回拼接后的字符串 MethodHandle intConcatenator = MethodHandles.lookup() .findStatic(String.class, "format", MethodType.methodType(String.class, String.class, Object[].class)) .bindTo("%d%d"); // 绑定格式化字符串,此时handle需要两个int参数 // 第一步:给intConcatenator的第二个参数绑定randomIntProvider(不是常量,是handle本身) // 此时得到的handle需要一个int参数(第一个参数),第二个参数会在调用时自动执行randomIntProvider获取 MethodHandle concatWithSecondRandom = MethodHandles.insertArguments(intConcatenator, 1, randomIntProvider); // 第二步:把concatWithSecondRandom的第一个参数也替换为randomIntProvider的调用 // foldArguments会自动用randomIntProvider的执行结果填充concatWithSecondRandom的第一个参数 MethodHandle finalNoArgHandle = MethodHandles.foldArguments(concatWithSecondRandom, randomIntProvider); // 测试:每次调用都会生成两个新的随机数 for (int i = 0; i < 3; i++) { String result = (String) finalNoArgHandle.invokeExact(); System.out.println("第" + (i+1) + "次调用结果:" + result); } } }
关键细节解释
insertArguments的正确用法:当你传入的参数是一个MethodHandle而非具体值时,JVM会在每次调用新生成的handle时,自动执行这个传入的handle来获取参数值——而不是提前计算一次就固定下来。foldArguments的作用:这个方法可以把目标handle的参数,替换为另一个handle的执行结果。这里我们用它把concatWithSecondRandom所需的第一个int参数,替换为randomIntProvider的调用结果,最终得到一个完全无参的MethodHandle。- 类型兼容性:确保所有MethodHandle的类型匹配,比如
randomIntProvider的返回类型必须和intConcatenator的参数类型一致(都是int)。
验证效果
运行上面的代码,你会看到每次调用finalNoArgHandle时,都会生成两个不同的随机数拼接结果,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Some Name
相关产品推荐
相关产品推荐

