Java的动态性支持学习五 - 方法句柄 概念和句柄类型
2013-01-10 16:03
525 查看
Java的动态性支持学习一 - 反射机制 概念概述
Java的动态性支持学习二 - 反射机制 属性、方法、对象的操作
Java的动态性支持学习三 - 反射机制 取消属性、方法、构造器的访问限制
Java的动态性支持学习四 - 反射调用的性能对比
Java的动态性支持学习五 - 方法句柄 概念和句柄类型
Java的动态性支持学习六 - 方法句柄 获取和调用
Java的动态性支持学习七 - 方法句柄调用的性能对比
方法句柄
Java 7增加了一个新的特性,使得Java语言对动态更好的支持,而且性能也有很大的提升,那就是方法句柄。方法句柄是对Java中方法、构造器、字段的一个强类型的可执行的引用。通过方法句柄可以直接调用该句柄所引用的底层方法。从作用上来说,方法句柄的作用类似于反射中的Method类,但方法句柄的功能更强大,使用更灵活,性能更好。
方法句柄的类型
方法句柄是由java.lang.invoke.MethodHandle类表示的。方法句柄的类型(MethodType)完全由它的返回类型和参数类型来确定的,和它所引用的底层方法的名称和所在的类没有关系。比如String类的length方法和Integer类的intValue方法的方法句柄类型是一样的。MethodType类的对象实例只能通过MethodType类中的静态工厂方法创建。这样的工厂方法工有三类。
创建方法句柄的类型
第一类是通过指定返回值和参数类型来创建MethodType,有多种重载,如下:
static MethodType methodType(Class<?> rtype) static MethodType methodType(Class<?> rtype, Class<?> ptype0) static MethodType methodType(Class<?> rtype, Class<?>[] ptypes) static MethodType methodType(Class<?> rtype, Class<?> ptype0, Class<?>... ptypes) static MethodType methodType(Class<?> rtype, List<Class<?>> ptypes) static MethodType methodType(Class<?> rtype, MethodType ptypes)
第一个参数rtype是返回类型,返回值类型是必须有的,如果返回值是void类型,可以用java.lang.Void.class或void.class来声明。可以有0或多个参数类型。
第二类是通过genericMethodType方法创建MethodType,有两种重载:
static MethodType genericMethodType(int objectArgCount) static MethodType genericMethodType(int objectArgCount, boolean finalArray)
genericMethodType生成通用的MethodType类型,它们的返回值和所有参数的类型都是Object类。objectArgCount参数的个数,finalArray用来说明是否在参数列表的后面添加一个Object[]类型的参数。
第三类比较复杂,是通过fromMethodDescriptorString方法创建MethodType类,声明如下:
static MethodType fromMethodDescriptorString(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的方法如下:
MethodType appendParameterTypes(Class<?>... ptypesToInsert) MethodType appendParameterTypes(List<Class<?>> ptypesToInsert) MethodType changeParameterType(int num, Class<?> nptype) MethodType changeReturnType(Class<?> nrtype) MethodType dropParameterTypes(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还有几个常用的方法:
MethodType wrap() 把基本类型转换成基本类型的包装类型 MethodType unwrap() 把基本类型的包装类型转换成基本类型 MethodType generic() 把返回值和参数类型都变成Object类型 MethodType erase() 只把引用类型都变成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();
相关文章推荐
- Java的动态性支持学习六 - 方法句柄 获取和调用
- Java的动态性支持学习一 - 反射机制 概念概述
- Java的动态性支持学习二 - 反射机制 属性、方法、对象的操作
- Java的动态性支持学习三 - 反射机制 取消属性、方法、构造器的访问限制
- ava的动态性支持学习七 - 方法句柄调用的性能对比
- Java8学习笔记 — 其它新特性【接口默认方法(静态方法)、重复注解、类型注解】
- java学习记录(三):引用类型的概念
- 学习笔记-java基本类型的包装类,常用方法
- C#学习基本概念之数据类型(2)---(C#与Java)
- 18天Java学习---13.面向对象编程08-Java中继承的概念,子类实例化过程,super()及方法复写
- Java学习笔记42:线程的几个方法和概念
- [bxd学习java基本点]13泛型类,泛型方法,当定义二种类型的泛型方法时,用迭代器的方法
- JavaWeb学习笔记之spring mvc处理方法支持如下的返回方式
- Java学习解疑1——Java支持的变量类型
- Java的动态性支持学习四 - 反射调用的性能对比
- JAVA基础 day13 String类和StringBUffer类的常用方法 基本数据类型包装类的学习
- [bxd学习java基本点]13泛型类,泛型方法,当定义二种类型的泛型方法时,用迭代器的方法
- 用类名做方法的返回值类型 在学习Java的初始阶段,很多同学使用基本数据类型定义变量和引用类型定义变量以及使用类名做方法的返回值类型常常不知所以。今天我以自己的解读方式和个人的理解作一个简单的解释,和
- 让BeanUtils的copyProperty方法支持String与java.util.Date的类型转换
- jdk7 新特性-Java语言的动态性-脚本语言支持api-方法调用05