关于反射,Nutz中提供了Mirror类。这里是该类的帮助文档Mirror帮助文档。
看过这个字段后,使用Mirror是没有什么问题了。
Mirror中提供了针对反射的方法操作非常之多,总体类说分为以下几类:
- 获取方法Method:获取所有方法或者指定方法,或者Getter方法
- 获取属性:获取所有属性或者指定属性
- 为指定的属性设置值
- 类型判断
- 其他工具类方法:
- 获取范型参数类型
- 根据注解查找属性
- 获取对象的构造器
底层实现都是使用java.lang.reflect包里面的类,如下所示:
java.lang.annotation.Annotation;
java.lang.reflect.Array;
java.lang.reflect.Constructor;
java.lang.reflect.Field;
java.lang.reflect.Method;
java.lang.reflect.Modifier;
java.lang.reflect.ParameterizedType;
java.lang.reflect.Type;
由于该Mirror类封装的方法众多,所以这里不一一说明,仅挑选自己平时也用的一些来说明
获取对象中指定属性的值。
Mirror中针对属性的值获取,主要有以下几种方式,
- 根据属性名获取该属性getter方法,然后调用getter方法获取属性值,伪代码如下:
return getGetter(propName).invok(object);
getGetter具体实现:使用propName来拼Getter方法名,使用"get" 和"is"开头来拼方法名。
- 另外一种方法是获取属性Field,然后调用Field.get(object)获取该属性值
第二种方法我自己之前很少使用,主要是没有对java api系统看,不知道有这个方法。
获取注解信息
通过反射获取注解本身很简单;但是注解的应用太广泛了,以至于很多人反而容易忽视这个东西,这个就叫做熟视无睹。
Mirror中提供了getAnnotation(Class annType)方法来获取一个类中的注解信息。
实现上也简单精巧:
do {
ann = cc.getAnnotation(annType);
cc = cc.getSuperclass();
} while (null == ann && cc != Object.class);
上述代码从当前类型本身获取指定注解,如果获取不到注解,就向上一层从父类获取,直到Object类型不在获取(不好喊Object).
lang中还有两个包也是为反射相关提供的功能,一个是org.nutz.lang.born,一个是org.nutz.lang.reflect
org.nutz.lang.born
born包中主要封装了有别于传统的new关键字创建对象的方法。
该package下有一个顶级接口Borning,该接口中定义了一个接口方法:
//通过给定参数生成一个对象
T born(Object... args);
其他类基本都实现了该接口,并且实现了born方法。挑选几个关键的说明下
ArrayBorning
顾名思义,根据一个参数生成一个对象数组;
这里注意,生成的对象数组中并没有对象数据,只是一个指定长度的空的对象数组,
ArrayBorning 的born方法虽然支持多个参数,单实际上只使用了第一个参数,且默认认为第一个参数为数字(初始化数组长度用)
Array.newInstance(eleType, ((Number) arg0).intValue());
实现通过调用java api中的java.lang.Array的newInstance方法
ConstructorBorning
- 根据构造函数对象,和构造参数生成一个对象
- ConstructorBorning 的构造方法中传入构造函数对象Constructor(有没有听绕口令的感觉), born方法中传入构造参数
- 具体实现也是调用java api中的Class的newInstance方法。
- ConstructorCastingBorning和ConstructorBorning逻辑,用法差不多,只不过加入了对范型的支持
小结
java虽然不是动态语言,但是通过反射机制也达到了一些动态语言具备的功能。对于嫌弃java语言不灵活的同学,可以多研究研究java的反射机制。说不定会发现java其实没有印象中那么死板。
nutz中还有一些反射相关的工具类,这里不一一说明,干說实在提不起兴趣,后面说多到其他模块用到这些基础模块的时候,再穿插的说吧。