方法句柄

Intro

Java通过反射可以在运行时动态获取或修改类型字段、方法等信息,但反射的执行速度也成一大诟病。Java7开始提供另一套API称为方法句柄(Method Handle),其作用与反射类似,但执行效率比反射高,被称为现代化反射。

A method handle is a typed, directly executable reference to an underlying method, constructor, field, or similar low-level operation, with optional transformations of arguments or return values.

方法句柄是一种指向方法的强类型、可执行的引用,它的类型由方法的参数类型和返回值类型组成,而与方法所在类名和方法名无关。 它作为方法的抽象,使方法调用不再受所在类型的约束,能更好的支持动态类型语言特性。

几个关键的类:

  • Lookup:方法句柄的创建工厂类,方法的检查工作是在创建时处理的而非调用时处理

  • MethodType:方法的签名,包括返回值类型和参数类型

  • MethodHandle:方法句柄,用于动态访问类型的信息

Lookup

创建一个提供对公共方法访问的查找:

MethodHandles.Lookup publicLookup = MethodHandles.publicLookup();

lookup方法可访问私有和受保护的方法

MethodHandles.Lookup lookup = MethodHandles.lookup();

Lookup对象提供几种查找对象的方法

  • invokevirtual

对象方法的查找

  • invokestatic

静态方法查找

  • 查找构造函数

  • 查找非私有字段

MethodHandle

使用invoke家族来调用

invokeinvokeWithArgumentsinvokeExact

MethodType

Lookup需要方法的签名才能找到方法句柄

rtype为返回值类型,ptypes为参数类型

QuickStart

如何设计统一的方式调用race方法?

使用反射有性能损耗,抽象出一个包含race方法的接口则增加了接口约束,这时候就可以考虑方法句柄了。将race方法抽象成方法句柄,它们的句柄类型一致,对调用者暴露方法句柄即可。

方法句柄也有权限问题,但与反射在方法调用时检查不同,它是在句柄创建阶段进行检查的,如果多次调用句柄,它比反射可以省下权限重复检查的开销。

但需注意的是,句柄的访问权限不取决于创建句柄的位置,而是 Lookup 对象的位置

Runtime#exec

getRuntime没有参数,对应的MethodType只要传一个Runtime.class即可

Last updated

Was this helpful?