如何使用 Java 中 Invoke 包?

1. methodHandle 调用

在过去,我们调用一个类的方法,除了直接调用,再就是使用反射来调用了。而今天我要说说 jdk 新引入的方式来调用。

比如我们有一个很简单的 UserService 类。

1
2
3
4
5
6
7
public class UserService {

  public String getUsername(String id) {
    return "username" + id;
  }

}

直接调用反射调用的方式比较简单,我就不说明了。

下面来演示 invoke 包的使用。

  • 使用 MethodHandles.lookup() 来查找对应的方法
  • 使用 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
35
36
37
38
39
40
41
42
43
public class UserServiceTest {

  private MethodType methodType;
  private Lookup lookup;
  private MethodHandle methodHandle;

  @SneakyThrows
  @BeforeEach
  public void beforeEach() {
    methodType = MethodType.methodType(String.class, String.class);
    lookup = MethodHandles.lookup();
    methodHandle = lookup.findVirtual(UserService.class, "getUsername", methodType);
  }

  @SneakyThrows
  @Test
  public void invokeWithArguments() {
    UserService userService = new UserService();
    Object obj = methodHandle.bindTo(userService).invokeWithArguments("1");
    assertEquals("username1", obj);

  }

  @SneakyThrows
  @Test
  public void invoke() {
    UserService userService = new UserService();
    Object obj = methodHandle.invoke(userService, "1");
    assertEquals("username1", obj);
  }

  /**
   * 要求类型全匹配, 包括返回值类型
   */
  @SneakyThrows
  @Test
  public void invokeExact() {
    UserService userService = new UserService();
    String s = (String) methodHandle.invokeExact(userService, "1");
    assertEquals("username1", s);
  }

}

2. 代码实现位置

github 地址

0%