import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; class SayHello{ public void say(String name){ System.out.print(String.format("%s,welcome to the hell ^_^...",name)); } } public class MethodHandleTest { public static void main(String[] args) throws Throwable { Object name = "Damon"; MethodType mType = MethodType.methodType(void.class, String.class);//新建方法签名对象 MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle mHandle = lookup.findVirtual(SayHello.class, "say", mType);//通过方法签名对象查找方法句柄 mHandle.invoke(SayHello.class.newInstance(),name);//调用 } }
java7中为间接调用方法引入了新的api,其中最关键的是java.lang.invoke包,即方法句柄。我们可以看成是java反射的升级版,但是它不反射那样有时候显得冗长、繁重的粗糙。
方法句柄中首先涉及到两个重要的类,MethodHandle和MethodType。
MethodHandle
它是可对直接执行的方法(或域、构造方法等)的类型的引用,或者说,它是一个有能力安全调用方法的对象。换个方法来说,通过句柄我们可以直接调用该句柄所引用的底层方法。从作用上来看,方法句柄类似于反射中的Method类,但是方法句柄的功能更加强大、使用更加灵活、性能也更好。
MethodType
它是表示方法签名类型的不可变对象。每个方法句柄都有一个MethodType实例,用来指明方法的返回类型和参数类型。它的类型完全由参数类型和方法类型来确定,而与它所引用的底层的方法的名称和所在的类没有关系。举个例子,例如String类的length方法和Integer类的intValue方法的方法句柄的类型就是一样的,因为这两个方法都没有参数,而且返回值类型都是int,则我们可以通过下列语句获取同一个方法类型:MethodType mt = MethodType.methodType(int.class);
MethodType的对象实例只能通过MethodType类中的静态工厂方法来创建,而且MethodType类的所有对象实例都是不可变的,类似于String类。如果修改了MethodType实例中的信息,就会生成另外一个MethodType实例。