概述
反射,基于类的运行时信息,通过类加载后的Class对象,获取类的方法,属性,利用Class对象调用方法和修改属性。
本节主要说下Field这个类,代表类的属性,包括实例字段和静态字段。
如果获取Field对象呢,主要通过Class对象的方法:
Class.getFields(), Class.getField(String),
Class.getDeclaredFields(), Class.getDeclaredField(String)
获取字段
从方法签名上看应该是2类方法,getField和getDeclaredField,这两类有什么区别呢?
1. getField
getField方法用获取public类型的字段(包括父类或者接口的字段),策略如下:
首先会在当前类中申明的public字段中查找,如果没有就递归查找接口中的字段,如果没有找到继续递归找父类中的public字段,如果还没找到,那么会抛出异常NoSuchFieldException。
当字段名相同时,getField方法会按照上面的顺序获取第一个遇到的字段。
getFields方法则会获取所有的public字段,包括接口和父类,如果没有public字段,那么返回长度为0的数组。
2. getDeclaredField
getDeclaredField方法会在当前类的声明中查找,但不会在父类或者父接口的字段中查找,如果没有找到,抛出NoSuchFieldException。
getDeclaredFields获取当前类中所有声明的字段,同样不会在父类中进行查找,如果没有则返回长度为0的数组。
第三方工具
有时候我们需要获取类中所有申明的属性(包括基类),自己写虽说只有几行代码,但确实没必要,我们可以直接使用org.apache.commons.lang3包中的FieldUtils工具类,提供了很多反射操作Field的静态方法,读取属性,属性赋值等,有兴趣可以看下这个类源码,下面的就是包中提供的获取所有字段的方法。
public static List<Field> getAllFieldsList(final Class<?> cls) {
Validate.isTrue(cls != null, "The class must not be null");
final List<Field> allFields = new ArrayList<Field>();
Class<?> currentClass = cls;
while (currentClass != null) {
final Field[] declaredFields = currentClass.getDeclaredFields();
for (final Field field : declaredFields) {
allFields.add(field);
}
currentClass = currentClass.getSuperclass();
}
return allFields;
}
个人认为还是需要积累点工具类,毕竟自己写的代码有一定的随意性,注释,代码规范、逻辑严谨性等都不如经过市场考验的公共方法,不过要用好第三方工具类,源码是必须要研读的。
字段赋值
通过Field字段进行赋值,可以使用public void set(Object obj, Object value)方法。此方法有些注意点:
- 此方法会先判断字段是否是public类型,如果为不为public类型,那么设置字段前必须通过Field.setAccessible(true)方法进行访问权限设置,不然会抛出异常:IllegalAccessException 。
- 如果字段为static类型,那么通过set方法进行赋值时,会忽略obj对象,因为静态字段属于类。
- 如果字段为final类型,不管是public还是 private,那么用set方法赋值时,只有setAccessible进行访问权限设置后,才能正确调用,不然会报异常:IllegalAccessException。但是对final字段进行set方法赋值时,尽管方法正常调用,但是并不会改变fianl字段的值。
- 如果字段为final static 类型,那么进行set方法赋值时,总会抛出IllegalAccessException异常。
最后
以上就是柔弱香菇为你收集整理的反射-Field的全部内容,希望文章能够帮你解决反射-Field所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复