当 MethodHandle 速度较快时,为什么要使用反射来访问类成员?

随着Java 7的发布,MethodHandle出现了,它允许用户调用一个方法,就好像使用其底层字节码一样。特别是,MethodHandles.Lookup 类提供了工厂方法来创建方法句柄来访问类成员:

Lookup 对象上的工厂方法对应于方法、构造函数和字段的所有主要用例。由工厂方法创建的每个方法句柄都是特定字节码行为的功能等效项。

从功能上讲,这或多或少等同于使用反射来访问这些相同的类成员,但方法句柄比反射更快

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

请注意,虽然方法句柄是在Java 7中引入的,但我的问题主要与Java 8有关,其中它们经过优化,被认为达到了与直接字段/方法调用大致相等的性能,超出了反射的能力。


答案 1

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

反射是一种通用的内省机制,它包括方法处理机制所缺少的许多功能,例如枚举类()的成员,检查成员的特征(例如其可访问性标志),检查成员的泛型签名等。Class.getMethods()

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

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

反射库针对主流Java用户;方法句柄层更针对编译器和语言运行时编写器。选择为作业设计的工具。


答案 2

博士编号如果可能,您应该使用(并且更喜欢)核心反射 API。MethodHandles

MethodHandles.Lookup access 说(部分),

与核心反射 API 不同,在核心反射 API 中,每次调用反射方法时都会检查访问权限,而方法句柄访问检查是在创建方法句柄时执行的


推荐