为什么在 MethodHandle 更快时使用反射来访问 class 成员?

Why use reflection to access class members when MethodHandle is faster?

随着 Java 7 的发布,MethodHandle, which allows a user to invoke a method as if using its underlying bytecode. In particular, the MethodHandles.Lookup class 提供工厂方法来创建方法句柄以访问 class 成员:

The factory methods on a Lookup object correspond to all major use cases for methods, constructors, and fields. Each method handle created by a factory method is the functional equivalent of a particular bytecode behavior.

在功能上,这或多或少等同于使用反射来访问这些相同的 class 成员,但 method handles are faster than reflection.

那么,是否有任何理由仍然使用像 Field#get(..)/Method.invoke(..) 这样的反射功能,或者这些方法是否随着更快的方法句柄的引入而有效地过时了?

请注意,虽然方法句柄是在 Java 7 中引入的,但我的问题主要与 Java 8 有关,其中它们经过优化,据称可以达到大约等于直接的性能field/method呼唤,超越反射的能力

tl;dr 不。您应该尽可能使用(并且更喜欢)MethodHandles 而不是核心反射 API。

MethodHandles.Lookup access 说(部分),

Unlike with the Core Reflection API, where access is checked every time a reflective method is invoked, method handle access checking is performed when the method handle is created.

反射和方法句柄有不同的用途,并且存在于不同的抽象级别。您应该使用适合您正在解决的问题的那个。

反射是一种通用的内省机制,它包含了方法句柄机制所缺乏的许多特性,例如枚举class(Class.getMethods())的成员,检查一个Class.getMethods()的特征成员,例如其可访问性标志、检查成员的通用签名等

此外,反射对象可以自由共享而无需向共享者授予访问权限,因为访问检查是在每次调用时进行的。另一方面,共享方法句柄赋予共享者调用的能力。所以它们也有不同的安全隐患。

方法句柄是一种用于查找、调整和调用方法的低级机制。虽然通过方法句柄调用比通过反射更快(尽管到目前为止,直接字节码调用通常仍然比方法句柄调用快),但方法句柄也更难使用,因为它们不会自动执行改编 Java用户会期望(例如将 String 参数转换为 Object),从而导致链接错误。

反射库面向主流Java用户;方法处理层更多地针对编译器和语言运行时编写者。选择专为工作设计的工具。