java类型句柄_Java的动态性支持学习五 - 方法句柄 概念和句柄类型

方法句柄

Java 7增加了一个新的特性,使得Java语言对动态更好的支持,而且性能也有很大的提升,那就是方法句柄。方法句柄是对Java中方法、构造器、字段的一个强类型的可执行的引用。通过方法句柄可以直接调用该句柄所引用的底层方法。从作用上来说,方法句柄的作用类似于反射中的Method类,但方法句柄的功能更强大,使用更灵活,性能更好。

方法句柄的类型

方法句柄是由java.lang.invoke.MethodHandle类表示的。方法句柄的类型(MethodType)完全由它的返回类型和参数类型来确定的,和它所引用的底层方法的名称和所在的类没有关系。比如String类的length方法和Integer类的intValue方法的方法句柄类型是一样的。MethodType类的对象实例只能通过MethodType类中的静态工厂方法创建。这样的工厂方法工有三类。

创建方法句柄的类型

第一类是通过指定返回值和参数类型来创建MethodType,有多种重载,如下:

static MethodTypemethodType(Class> rtype)

static MethodTypemethodType(Class> rtype, Class> ptype0)

static MethodTypemethodType(Class> rtype, Class>[] ptypes)

static MethodTypemethodType(Class> rtype, Class> ptype0, Class>... ptypes)

static MethodTypemethodType(Class> rtype, List> ptypes)

static MethodTypemethodType(Class> rtype, MethodType ptypes)

第一个参数rtype是返回类型,返回值类型是必须有的,如果返回值是void类型,可以用java.lang.Void.class或void.class来声明。可以有0或多个参数类型。

第二类是通过genericMethodType方法创建MethodType,有两种重载:

static MethodTypegenericMethodType(int objectArgCount)

static MethodTypegenericMethodType(int objectArgCount, boolean finalArray) genericMethodType生成通用的MethodType类型,它们的返回值和所有参数的类型都是Object类。objectArgCount参数的个数,finalArray用来说明是否在参数列表的后面添加一个Object[]类型的参数。

第三类比较复杂,是通过fromMethodDescriptorString方法创建MethodType类,声明如下:

static MethodTypefromMethodDescriptorString(String descriptor, ClassLoader loader)

不是很好理解,适合于对Java字节代码格式比较熟悉的开发人员,如String.getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)方法的类型在字节码中表示的形式是"(II[CI)V"。

loader是类的加载器,该加载器用来加载方法类型表达式中出现的Java类。

创建MethodType的Demo如下:

//第一类

MethodType mt1 = MethodType.methodType(int.class);

MethodType mt2 = MethodType.methodType(String.class, String.class);

//第二类

MethodType mt3 = MethodType.genericMethodType(3);

MethodType mt4 = MethodType.genericMethodType(2, true);

//第三类

ClassLoader cl = this.getClass().getClassLoader();

String descriptor = "(Ljava/lang/String;)Ljava/lang/String;";

MethodType mt5 = MethodType.fromMethodDescriptorString(descriptor, cl);

更改MethodType

MethodType类的所有对象实例都是不可变的,类似于String类,所有对MethodType类对象的修改,都会产生一个新的MethodType类对象。两个MethodType类对象是否相等,只取决于他们所包含的参数类型和返回值类型是否完全一致。改变MethodType的方法如下:

MethodTypeappendParameterTypes(Class>... ptypesToInsert)

MethodTypeappendParameterTypes(List> ptypesToInsert)

MethodTypechangeParameterType(int num, Class> nptype)

MethodTypechangeReturnType(Class> nrtype)

MethodTypedropParameterTypes(int start, int end)

Demo如:

//(int,int)String

MethodType mt = MethodType.methodType(String.class, int.class, int.class);

//(int,int,float)String

mtmt = mt.appendParameterTypes(float.class);

//(int,double,long,int,float)String

mtmt = mt.insertParameterTypes(1, double.class, long.class);

//(int,double,int,float)String

mtmt = mt.dropParameterTypes(2, 3);

//(int,double,String,float)String

mtmt = mt.changeParameterType(2, String.class);

//(int,double,String,float)void

mtmt = mt.changeReturnType(void.class);

MethodType还有几个常用的方法:

MethodTypewrap() 把基本类型转换成基本类型的包装类型

MethodTypeunwrap() 把基本类型的包装类型转换成基本类型

MethodTypegeneric() 把返回值和参数类型都变成Object类型

MethodTypeerase() 只把引用类型都变成Object类型,基本类型不做处理

Demo如:

//(int,double)Integer

MethodType mt = MethodType.methodType(Integer.class, int.class, double.class);

//(Integer,Double)Integer

MethodType wrapped = mt.wrap();

//(int,double)int

MethodType unwrapped = mt.unwrap();

//(Object,Object)Object

MethodType generic = mt.generic();

//(int,double)Object

MethodType erased = mt.erase();

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值