• FieldUtils 工具类使用

    类路径:org.apache.commons.lang3.reflect.FieldUtils
    版本:commons-lang3:3.7
    Java doc:FieldUtils API
    说明:FieldUtils是一个通过反射处理字段的实用工具类,它提供的方法超出了普通编码的范围,可以修改不应该修改的字段,应该谨慎使用该工具类

    FieldUtils 类图

    FieldUtils 类图

    构造方法

    FieldUtils()
    

    获取类字段

    /**
     *
     * @param cls 查询的类,不允许为空
     * @return 返回一个字段数组(可能为空).
     * @throws IllegalArgumentException 类为null时抛出无效参数异常
     */
    static Field[] getAllFields(Class<?> cls)
    
    /**
     *
     * @param cls 查询的类,不允许为空
     * @return 返回一个字段列表(可能为空).
     * @throws IllegalArgumentException 类为null时抛出无效参数异常
     */
    static List<Field> getAllFieldsList(Class<?> cls)
    
    /**
     *
     * @param cls 查询的类,不允许为空
     * @param fieldName 字段名称
     * @return 字段对象
     * @throws IllegalArgumentException 类为null时抛出无效参数异常
     */
    static Field getDeclaredField(Class<?> cls, String fieldName)
    
    /**
     * @param cls 查询的类,不允许为空
     * @param fieldName 字段名称
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @return 字段对象
     * @throws IllegalArgumentException 类为null时抛出无效参数异常
     */
    static Field getDeclaredField(final Class<?> cls, final String fieldName, final boolean forceAccess)
    
    /**
     *
     * @param cls 查询的类,不允许为空
     * @param fieldName 字段名称
     * @return 字段对象
     * @throws IllegalArgumentException 类为null时抛出无效参数异常
     */
    static Field getField(Class<?> cls, String fieldName)
    
    /**
     * @param cls 查询的类,不允许为空
     * @param fieldName 字段名称
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @return 字段对象
     * @throws IllegalArgumentException 类为null时抛出无效参数异常
     */
    static Field getField(final Class<?> cls, final String fieldName, final boolean forceAccess)
    
    /**
     * @param cls 查询的类,不允许为空
     * @param annotationCls 查询的注解,该注解必须允许在字段上使用
     * @return 字段列表(可能为空)
     * @throws IllegalArgumentException 注解为null时抛出无效参数异常
     */
    static List<Field>	getFieldsListWithAnnotation(Class<?> cls, Class<? extends Annotation> annotationCls)
    
    /**
     * @param cls 查询的类,不允许为空
     * @param annotationCls 查询的注解,该注解必须允许在字段上使用
     * @return 字段数组(可能为空)
     * @throws IllegalArgumentException 注解为null时抛出无效参数异常
     */
    static Field[]	getFieldsWithAnnotation(Class<?> cls, Class<? extends Annotation> annotationCls)
    

    读取字段值

    /**
     * @param target 目标对象
     * @param fieldName 字段名称
     * @return 字段值
     * @throws IllegalArgumentException 如果对象为null,或者字段名称为空或者找不到,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static Object readDeclaredField(Object target, String fieldName)
    
    /**
     * @param target 目标对象
     * @param fieldName 字段名称
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @return 字段值
     * @throws IllegalArgumentException 如果对象为null,或者字段名称为空或者找不到,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static Object readDeclaredField(Object target, String fieldName, boolean forceAccess)
    
    /**
     * @param cls 查询的类,不允许为空
     * @param fieldName 字段名称
     * @return 字段值
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static Object readDeclaredStaticField(Class<?> cls, String fieldName)
    
    /**
     * @param cls 查询的类,不允许为空
     * @param fieldName 字段名称
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @return 字段值
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static Object readDeclaredStaticField(Object target, String fieldName, boolean forceAccess)
    
    /**
     * @param field 字段对象
     * @param target 目标对象
     * @return 字段值
     * @throws IllegalArgumentException 如果目标对象为null,或者字段对象为null,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static Object readField(Field field, Object target)
    
    /**
     * @param field 字段对象
     * @param target 目标对象
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @return 字段值
     * @throws IllegalArgumentException 如果目标对象为null,或者字段对象为null,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static Object readField(Field field, Object target, boolean forceAccess)
    
    /**
     * @param target 目标对象
     * @param fieldName 字段名称
     * @return 字段值
     * @throws IllegalArgumentException 如果对象为null,或者字段名称为空或者找不到,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static Object readField(Object target, String fieldName)
    
    /**
     * @param target 目标对象
     * @param fieldName 字段名称
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @return 字段值
     * @throws IllegalArgumentException 如果对象为null,或者字段名称为空或者找不到,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static Object readField(Object target, String fieldName, boolean forceAccess)
    
    /**
     * @param cls 查询的类,不允许为空
     * @param fieldName 字段名称
     * @return 字段值
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static Object readStaticField(Class<?> cls, String fieldName)
    
    /**
     * @param cls 查询的类,不允许为空
     * @param fieldName 字段名称
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @return 字段值
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static Object readStaticField(Object target, String fieldName, boolean forceAccess)
    
    /**
     * @param field 字段对象
     * @return 字段值
     * @throws IllegalArgumentException 如果字段为null,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static Object readStaticField(Field field)
    
    /**
     * @param field 字段对象
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @return 字段值
     * @throws IllegalArgumentException 如果字段为null,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static Object readStaticField(Field field, boolean forceAccess)
    

    删除字段final修饰符

    /**
     * @param field 字段对象
     * @throws IllegalArgumentException 如果字段为null,抛出无效参数异常
     */
    static void	removeFinalModifier(Field field)
    
    /**
     * @param field 字段对象
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @throws IllegalArgumentException 如果字段为null,抛出无效参数异常
     */
    static void	removeFinalModifier(Field field, boolean forceAccess)
    

    设置字段值

    /** 
     * @param target 目标对象
     * @param fieldName 字段名称
     * @param value 字段值
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static void	writeDeclaredField(Object target, String fieldName, Object value)
    
    /** 
     * @param target 目标对象
     * @param fieldName 字段名称
     * @param value 字段值
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static void	writeDeclaredField(Object target, String fieldName, Object value, boolean forceAccess)
    
    /** 
     * @param cls 设置的类,不允许为空
     * @param fieldName 字段名称
     * @param value 字段值
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static void	writeDeclaredStaticField(Class<?> cls, String fieldName, Object value)
    
    /** 
     * @param cls 设置的类,不允许为空
     * @param fieldName 字段名称
     * @param value 字段值
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static void	writeDeclaredStaticField(Class<?> cls, String fieldName, Object value, boolean forceAccess)
    
    /** 
     * @param field 字段对象
     * @param target 目标对象
     * @param value 字段值
     * @throws IllegalArgumentException 如果类为null,或者字段为null,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static void	writeField(Field field, Object target, Object value)
    
    /** 
     * @param field 字段对象
     * @param target 目标对象
     * @param value 字段值
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @throws IllegalArgumentException 如果类为null,或者字段为null,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static void	writeField(Field field, Object target, Object value, boolean forceAccess)
    
    /** 
     * @param target 目标对象
     * @param fieldName 字段名称
     * @param value 字段值
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static void	writeField(Object target, String fieldName, Object value)
    
    /** 
     * @param target 目标对象
     * @param fieldName 字段名称
     * @param value 字段值
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static void	writeField(Object target, String fieldName, Object value, boolean forceAccess)
    
    /** 
     * @param cls 设置的类,不允许为空
     * @param fieldName 字段名称
     * @param value 字段值
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static void	writeStaticField(Class<?> cls, String fieldName, Object value)
    
    /** 
     * @param cls 设置的类,不允许为空
     * @param fieldName 字段名称
     * @param value 字段值
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @throws IllegalArgumentException 如果类为null,或者字段名称为空或者找不到,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static void	writeStaticField(Class<?> cls, String fieldName, Object value, boolean forceAccess)
    
    /** 
     * @param field 字段对象
     * @param value 字段值
     * @throws IllegalArgumentException 如果字段为null,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,抛出无效访问异常
     */
    static void	writeStaticField(Field field, Object value)
    
    /** 
     * @param field 字段对象
     * @param value 字段值
     * @param forceAccess 是否强制访问(参考 java.lang.reflect.AccessibleObject#setAccessible(boolean))
     * @throws IllegalArgumentException 如果字段为null,或者字段值没有分配,抛出无效参数异常
     * @throws IllegalAccessException 如果字段不是公有,并且没有设置强制访问,抛出无效访问异常
     */
    static void	writeStaticField(Field field, Object value, boolean forceAccess)
    

    使用示例

    static class Parent {
        public static final Integer PARENT_ID = 0;
        private static final String PARENT_NAME = "PARENT";
        private Integer parentId = 0;
        public String parentName = "PARENT";
        @DateTimeFormat
        private Date parentBorn = new Date();
    }
    
    static class Child extends Parent {
        public static final Integer CHILD_ID = 1;
        private static final String CHILD_NAME = "CHILD";
        private Integer childId = 1;
        public String childName = "CHILD";
        @DateTimeFormat
        public Date childBorn = new Date();
    }
    
    @Test
    @DisplayName("FieldUtils 工具类 - 获取类字段")
    void getFieldTest() {
        FieldUtils.getAllFields(Child.class);
        /* Field[10]
         * 0 = {Field} "public static final java.lang.Integer x.x.AppTest$Child.CHILD_ID"
         * 1 = {Field} "private static final java.lang.String x.x.AppTest$Child.CHILD_NAME"
         * 2 = {Field} "private java.lang.Integer x.x.AppTest$Child.childId"
         * 3 = {Field} "public java.lang.String x.x.AppTest$Child.childName"
         * 4 = {Field} "public java.util.Date x.x.AppTest$Child.childBorn"
         * 5 = {Field} "public static final java.lang.Integer x.x.AppTest$Parent.PARENT_ID"
         * 6 = {Field} "private static final java.lang.String x.x.AppTest$Parent.PARENT_NAME"
         * 7 = {Field} "private java.lang.Integer x.x.AppTest$Parent.parentId"
         * 8 = {Field} "public java.lang.String x.x.AppTest$Parent.parentName"
         * 9 = {Field} "private java.util.Date x.x.AppTest$Parent.parentBorn"
         */
        FieldUtils.getAllFieldsList(Child.class);
        /* ArrayList size = 10
         * 0 = {Field} "public static final java.lang.Integer x.x.AppTest$Child.CHILD_ID"
         * 1 = {Field} "private static final java.lang.String x.x.AppTest$Child.CHILD_NAME"
         * 2 = {Field} "private java.lang.Integer x.x.AppTest$Child.childId"
         * 3 = {Field} "public java.lang.String x.x.AppTest$Child.childName"
         * 4 = {Field} "public java.util.Date x.x.AppTest$Child.childBorn"
         * 5 = {Field} "public static final java.lang.Integer x.x.AppTest$Parent.PARENT_ID"
         * 6 = {Field} "private static final java.lang.String x.x.AppTest$Parent.PARENT_NAME"
         * 7 = {Field} "private java.lang.Integer x.x.AppTest$Parent.parentId"
         * 8 = {Field} "public java.lang.String x.x.AppTest$Parent.parentName"
         * 9 = {Field} "private java.util.Date x.x.AppTest$Parent.parentBorn"
         */
    
        FieldUtils.getDeclaredField(Parent.class, "parentName");
        // public java.lang.String x.x.AppTest$Parent.parentName
        FieldUtils.getDeclaredField(Child.class, "parentName");
        // null (只读取当前类字段)
        FieldUtils.getDeclaredField(Parent.class, "parentId");
        // null (不可访问)
    
        FieldUtils.getDeclaredField(Parent.class, "parentId", true);
        // private java.lang.Integer x.x.AppTest$Parent.parentId
    
        FieldUtils.getField(Child.class, "parentId");
        // null (不可访问)
        FieldUtils.getField(Child.class, "parentId", true);
        // private java.lang.Integer x.x.AppTest$Parent.parentId
    
        FieldUtils.getFieldsWithAnnotation(Child.class, DateTimeFormat.class);
        /* Field[2]
         * 0 = {Field@1549} "public java.util.Date x.x.AppTest$Child.childBorn"
         * 1 = {Field@1550} "private java.util.Date x.x.AppTest$Parent.parentBorn"
         */
        FieldUtils.getFieldsListWithAnnotation(Child.class, DateTimeFormat.class);
        /* ArrayList size = 2
         * 0 = {Field@1549} "public java.util.Date x.x.AppTest$Child.childBorn"
         * 1 = {Field@1550} "private java.util.Date x.x.AppTest$Parent.parentBorn"
         */
    }
    
    @Test
    @DisplayName("FieldUtils 工具类 - 读取类字段值")
    void readFieldTest() throws IllegalAccessException {
        Child child = new Child();
        FieldUtils.readDeclaredField(child, "parentId");
        // java.lang.IllegalArgumentException: Cannot locate declared field class x.x.AppTest$Child.parentId (只读取当前类)
        FieldUtils.readDeclaredField(child, "childId");
        // java.lang.IllegalArgumentException: Cannot locate declared field class x.x.AppTest$Child.childId (不可访问)
        FieldUtils.readDeclaredField(child, "childName");
        // CHILD
        FieldUtils.readDeclaredField(child, "CHILD_NAME");
        // java.lang.IllegalArgumentException: Cannot locate declared field class x.x.AppTest$Child.CHILD_NAME (不能读取静态字段)
        FieldUtils.readDeclaredField(child, "childId", true);
        // 1
    
        FieldUtils.readDeclaredStaticField(Child.class, "CHILD_NAME");
        // java.lang.IllegalArgumentException: Cannot locate declared field x.x.AppTest$Child.CHILD_NAME (不可访问)
        FieldUtils.readDeclaredStaticField(Child.class, "CHILD_ID");
        // 1
    
        FieldUtils.readDeclaredStaticField(Child.class, "CHILD_NAME", true);
        // CHILD
    
        FieldUtils.readField(child, "parentId");
        // java.lang.IllegalArgumentException: Cannot locate field parentId on class x.x.AppTest$Child (不可访问)
    
        FieldUtils.readField(child, "parentId", true);
        // 1
    
        FieldUtils.readField(FieldUtils.getField(Parent.class, "parentId", true), child);
        // 0
    }
    
    @Test
    @DisplayName("FieldUtils 工具类 - 设置类字段值")
    void writeFieldTest() throws IllegalAccessException {
        Child child = new Child();
        FieldUtils.writeField(child, "parentId", 2);
        // java.lang.IllegalArgumentException: Cannot locate declared field x.x.AppTest$Child.parentId (不可访问)
    
        FieldUtils.writeField(child, "parentId", 2, true);
        // (设置成功)
        FieldUtils.writeField(child, "parentId", "PARENT_NAME", true);
        // java.lang.IllegalArgumentException: Can not set java.lang.Integer field x.x.AppTest$Parent.parentId to java.lang.String (类型转换错误)
    
        Field field = FieldUtils.getField(Child.class, "CHILD_NAME", true);
        FieldUtils.writeStaticField(field, "CHILD_NAME2", true);
        // java.lang.IllegalAccessException: Can not set static final java.lang.String field x.x.AppTest$Child.CHILD_NAME to java.lang.String (不可设置final字段)
        FieldUtils.removeFinalModifier(field, true);
        // (移除final修饰符)
        FieldUtils.writeStaticField(field, "CHILD_NAME2", true);
        // (设置成功)
        FieldUtils.readStaticField(field);
        // CHILD_NAME2
    }