在 Java 中,方法句柄(MethodHandle) 是 java.lang.invoke 包 提供的一种对 方法、构造函数、字段等成员的引用方式,相比传统的反射(Reflection),更高效、类型安全、支持运行时动态绑定。
🧠 一、什么是方法句柄?
方法句柄(MethodHandle) 是一种可以直接调用的、类似函数指针的机制,代表一个可执行的方法、构造器或字段访问操作。
它是 Java 7 引入的底层机制,配合 invokedynamic,用于支持动态语言特性(例如 Lambda 表达式、Groovy、Kotlin 等)。
📦 核心类:
🚀 二、获取方法句柄的方式
使用 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
🔍 小贴士
🧪 四、方法句柄 vs 反射性能对比
✅ 总结一句话:
方法句柄(MethodHandle)是 Java 对方法、构造器、字段的高性能、类型安全的“函数指针”式调用机制,是 Lambda、invokedynamic 背后的核心技术。
评论区