侧边栏壁纸
博主头像
ProSayJ 博主等级

Talk is cheap. Show me the code.

  • 累计撰写 55 篇文章
  • 累计创建 20 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

什么是Java中的“方法句柄”?

YangJian
2025-07-01 / 0 评论 / 0 点赞 / 2 阅读 / 0 字

在 Java 中,方法句柄(MethodHandle) 是 java.lang.invoke 包 提供的一种对 方法、构造函数、字段等成员的引用方式,相比传统的反射(Reflection),更高效、类型安全、支持运行时动态绑定


🧠 一、什么是方法句柄?


方法句柄(MethodHandle) 是一种可以直接调用的、类似函数指针的机制,代表一个可执行的方法、构造器或字段访问操作。

它是 Java 7 引入的底层机制,配合 invokedynamic,用于支持动态语言特性(例如 Lambda 表达式、Groovy、Kotlin 等)。

📦 核心类:

类名

作用

MethodHandles

提供获取句柄的工厂方法(查找器)

MethodHandle

抽象类,表示指向方法的句柄

MethodType

描述方法签名(返回值类型和参数类型)


🚀 二、获取方法句柄的方式

使用 MethodHandles.Lookup 类中的方法获取,如下:

MethodHandles.Lookup lookup = MethodHandles.lookup();

✍️ 三、示例:通过方法句柄调用构造器创建对象

1. 示例类:

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
        System.out.println("Person created: " + name);
    }
}

2. 使用方法句柄调用构造器:

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class MethodHandleConstructorDemo {
    public static void main(String[] args) throws Throwable {
        // 获取构造方法的签名:返回值是Person,参数是String
        MethodType constructorType = MethodType.methodType(void.class, String.class);

        // 获取构造器方法句柄
        MethodHandles.Lookup lookup = MethodHandles.lookup();
        MethodHandle constructorHandle = lookup.findConstructor(Person.class, constructorType);

        // 调用构造器,创建对象
        Person person = (Person) constructorHandle.invoke("Tom");
    }
}

3. 通过 MethodHandle 调用普通方法、静态方法、字段访问的:

(基于 Java 8+)


✅ 示例类 User

public class User {
    private String name;

    public User() {
        this.name = "default";
    }

    public User(String name) {
        this.name = name;
    }

    public String sayHello(String prefix) {
        return prefix + ", " + name;
    }

    public static String staticGreet(String who) {
        return "Hello " + who + " (from static)";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

✅ 演示代码:调用普通方法、静态方法、字段访问(getter/setter)

import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;

public class MethodHandleDemo {
    public static void main(String[] args) throws Throwable {
        MethodHandles.Lookup lookup = MethodHandles.lookup();

        // 1️⃣ 调用实例方法 sayHello
        MethodType sayHelloType = MethodType.methodType(String.class, String.class);
        MethodHandle sayHelloHandle = lookup.findVirtual(User.class, "sayHello", sayHelloType);

        User user = new User("Alice");
        String result = (String) sayHelloHandle.invoke(user, "Hi");
        System.out.println("sayHello result: " + result); // 👉 Hi, Alice

        // 2️⃣ 调用静态方法 staticGreet
        MethodType staticGreetType = MethodType.methodType(String.class, String.class);
        MethodHandle staticGreetHandle = lookup.findStatic(User.class, "staticGreet", staticGreetType);
        String staticResult = (String) staticGreetHandle.invoke("Bob");
        System.out.println("staticGreet result: " + staticResult); // 👉 Hello Bob (from static)

        // 3️⃣ 字段 getter:name
        MethodHandle getter = lookup.findGetter(User.class, "name", String.class);
        String nameValue = (String) getter.invoke(user);
        System.out.println("getter result: " + nameValue); // 👉 Alice

        // 4️⃣ 字段 setter:name
        MethodHandle setter = lookup.findSetter(User.class, "name", String.class);
        setter.invoke(user, "Charlie");
        System.out.println("new name after setter: " + user.getName()); // 👉 Charlie
    }
}

✅ 输出示例

sayHello result: Hi, Alice
staticGreet result: Hello Bob (from static)
                               getter result: Alice
new name after setter: Charlie

🔍 小贴士

操作类型

API 示例

实例方法

findVirtual(Class, methodName, MethodType)

静态方法

findStatic(Class, methodName, MethodType)

构造方法

findConstructor(Class, MethodType)

字段 Getter

findGetter(Class, fieldName, fieldType)

字段 Setter

findSetter(Class, fieldName, fieldType)


🧪 四、方法句柄 vs 反射性能对比

特性

MethodHandle

Reflection

类型检查

编译时

运行时

性能

更快(支持 JIT 内联)

较慢(反射开销大)

可用场景

高性能框架、Lambda

动态字段、方法访问

安全性

更强

可能破坏封装性


✅ 总结一句话:

方法句柄(MethodHandle)是 Java 对方法、构造器、字段的高性能、类型安全的“函数指针”式调用机制,是 Lambda、invokedynamic 背后的核心技术。


0

评论区