514. Java 方法句柄 - 转换

514. Java 方法句柄 - 转换

到目前为止,我们看到 MethodHandle 不仅仅是对某个方法的直接引用。
它还可以通过 转换(transformations) 被“包装”成新的方法句柄,从而支持更灵活的操作。

常见的转换包括:

  • 类型转换(Type Transformation)
  • 参数重排(Permute Arguments)

这些转换的核心思想是:
原始 MethodHandle 始终存在,而转换得到的新句柄在外层“套了一层逻辑”,会在调用前后对参数和返回值做适配。


1. 类型转换 (asType) 🔄

有时我们需要调整 MethodHandle 的参数或返回值类型,使其与调用方的需求匹配。
这可以通过 asType 方法实现。

示例

假设我们有一个方法,接收 Object 参数并返回 String:

public static String test(Object obj) {
    return "Value: " + obj.toString();
}

查找对应的 MethodHandle:

MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodHandle target = lookup.findStatic(
        Example.class, 
        "test",
        MethodType.methodType(String.class, Object.class));

现在我们想适配成 接收 String 参数的句柄:

MethodHandle adapter = target.asType(
        MethodType.methodType(String.class, String.class));

测试调用:

String result1 = (String) target.invoke(111);      // ✔ 输出 "Value: 111"
System.out.println(result1);
String result2 = (String) adapter.invoke("hello"); // ✔ 输出 "Value: hello"
System.out.println(result2);
String result3 = (String) adapter.invoke(111);     // ❌ 抛 WrongMethodTypeException
System.out.println(result3);

👉 注意:

  • asType 允许我们在调用时进行类型适配。
  • 如果类型不能安全转换(如 Integer -> String),就会抛 WrongMethodTypeException。
  • 实际上,每次 invoke() 内部都会隐式调用一次 asType 来尝试类型适配。

2. 参数重排 (permuteArguments) 🔀

有时我们需要改变方法的参数顺序,可以用 permuteArguments 来实现。

示例

定义一个方法,接收多个不同类型的参数:

public static void test(int v1, String v2, long v3, boolean v4) {
    System.out.println(v1 + v2 + v3 + v4);
}

找到对应的 MethodHandle:

MethodHandle target = lookup.findStatic(
        Example.class,
        "test",
        MethodType.methodType(void.class, int.class, String.class, long.class, boolean.class));

我们希望参数顺序改成:boolean, long, String, int。
使用 permuteArguments:

MethodHandle reversed = MethodHandles.permuteArguments(
        target,
        MethodType.methodType(void.class, boolean.class, long.class, String.class, int.class),
        3, 2, 1, 0);

reversed.invoke(false, 1L, "str", 123);
// 输出: "123str1false"

参数说明

  • 第一个参数:原始 MethodHandle。
  • 第二个参数:新的 MethodType(即新的参数顺序)。
  • 第三个参数起:索引数组,表示新顺序下的参数如何映射到原顺序。

👉 这里 3, 2, 1, 0 表示:

  • 新的第 1 个参数(boolean)对应原来的第 4 个参数。
  • 新的第 2 个参数(long)对应原来的第 3 个参数。
  • 新的第 3 个参数(String)对应原来的第 2 个参数。
  • 新的第 4 个参数(int)对应原来的第 1 个参数。

🎯 总结

  • asType:用来做 参数/返回值的类型适配。
    • 适用于更严格的调用契约,比如把 (Object)->String 转成 (String)->String。
    • 如果类型不兼容会抛异常。
  • permuteArguments:用来 重新排列方法参数顺序。
    • 适用于方法签名和调用方需求不一致,但逻辑相同的情况。

📌 类比比喻:

  • asType 像 接口转换器,把接口换成你想要的形状。
  • permuteArguments 像 插拔电线,把参数插槽顺序重新排列。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容