7.6 变量处理和方法处理 7.6.1 Java9增强的MethodHandle

7.6 变量处理和方法处理

Java9引入了一个新的VarHandle类,并增强了原有的MethodHandle类。通过这两个类,允许Java像动态语言一样引用变量、引用方法,并调用它们。

7.6.1 Java9增强的MethodHandle

MethodHandleJava增加了方法引用的功能,方法引用的概念有点类似于C的”函数指针”。这种方法引用是一种轻量级的引用方式,它不会检查方法的访问权限,也不管方法所属的类、实例方法或静态方法, MethodHandle就是简单代表特定的方法,并可通过MethodHandle来调用方法。
为了使用MethodHandle,还涉及如下几个类。

描述
MethodHandles MethodHandle的工厂类,它提供了一系列静态方法用于获取MethodHandle
MethodHandles.Lookup Lookup静态内部类也是MethodHandleVarHandle的工厂类,专门用于获取MethodHandleVarHandle
MethodType 代表一个方法类型。 MethodType根据方法的形参、返回值类型来确定方法类型下面程序示范了MethodHandle的用法。

程序示例

下面程序示范了MethodHandle的用法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
import java.lang.invoke.*;

public class MethodHandleTest
{
// 定义一个private的类方法
private static void hello()
{
System.out.println("Hello world!");
}
// 定义一个private的实例方法
private String hello(String name)
{
System.out.println("执行带参数的hello" + name);
return name + ",您好";
}
public static void main(String[] args) throws Throwable
{
// 定义一个返回值为void、不带形参的方法类型
MethodType type = MethodType.methodType(void.class);
// 使用MethodHandles.Lookup的findStatic获取类方法
MethodHandle mtd = MethodHandles.lookup()
.findStatic(MethodHandleTest.class, "hello", type);
// 通过MethodHandle执行方法
mtd.invoke();

// 使用MethodHandles.Lookup的findVirtual获取实例方法
MethodHandle mtd2 = MethodHandles.lookup()
.findVirtual(MethodHandleTest.class, "hello",
// 指定获取返回值为String, 形参为String的方法类型
MethodType.methodType(String.class, String.class));
// 通过MethodHandle执行方法,传入主调对象和参数
System.out.println(mtd2.invoke(new MethodHandleTest(), "孙悟空"));
}
}

程序使用MethodHandles.Look对象根据类、方法名、方法类型来获取Methodhandle对象。由于此处的方法名只是一个字符串,而该字符串可以来自于变量、配置文件等,这意味着通过MethodHandle可以让Java动态调用某个方法