代码之家  ›  专栏  ›  技术社区  ›  benzen

Java中通过反射访问私有继承字段

  •  102
  • benzen  · 技术社区  · 15 年前

    我找到了通过 class.getDeclaredFields(); 并通过 class.getFields() 但我在找私人继承的领域。 我怎样才能做到这一点?

    7 回复  |  直到 10 年前
        1
  •  132
  •   aioobe    6 年前

    这应该说明如何解决它:

    import java.lang.reflect.Field;
    
    class Super {
        private int i = 5;
    }
    
    public class B extends Super {
        public static void main(String[] args) throws Exception {
            B b = new B();
            Field f = b.getClass().getSuperclass().getDeclaredField("i");
            f.setAccessible(true);
            System.out.println(f.get(b));
        }
    }
    

    (或 Class.getDeclaredFields 所有字段的数组。)

    输出:

    5
    
        2
  •  45
  •   Felk    8 年前

    这里最好的方法是使用 Visitor Pattern 找到类和所有超类中的所有字段并对它们执行回调操作。


    实施

    Spring有一个很好的实用类 ReflectionUtils 这就是:它定义了一个方法,通过回调在所有超类的所有字段上循环: ReflectionUtils.doWithFields()

    对目标类中的所有字段调用给定的回调, 向上移动类层次结构以获取所有声明的字段。




    -ff—确定要应用回调的字段的筛选器

    ReflectionUtils.doWithFields(RoleUnresolvedList.class,
        new FieldCallback(){
    
            @Override
            public void doWith(final Field field) throws IllegalArgumentException,
                IllegalAccessException{
    
                System.out.println("Found field " + field + " in type "
                    + field.getDeclaringClass());
    
            }
        },
        new FieldFilter(){
    
            @Override
            public boolean matches(final Field field){
                final int modifiers = field.getModifiers();
                // no static fields please
                return !Modifier.isStatic(modifiers);
            }
        });
    

    输出:

    找到了私有字段javax.management.relation关系.RoleUnresolvedList.typeSafe文件在类型类中javax.management.relation关系.RoleUnresolvedList文件

    找到字段私有瞬态java.lang.Object对象[] java.util.ArrayList.elementData文件在类型类中java.util.ArrayList

    找到受字段保护的瞬态intjava.util.AbstractList.modCount文件在类型类中java.util.AbstractList

        3
  •  35
  •   jqno    9 年前

    这样就可以了:

    private List<Field> getInheritedPrivateFields(Class<?> type) {
        List<Field> result = new ArrayList<Field>();
    
        Class<?> i = type;
        while (i != null && i != Object.class) {
            Collections.addAll(result, i.getDeclaredFields());
            i = i.getSuperclass();
        }
    
        return result;
    }
    

    如果你使用代码覆盖工具 EclEmma ,您必须注意:它们为每个类添加了一个隐藏字段。对于EclEmma,这些字段被标记 合成的 ,您可以这样过滤它们:

    private List<Field> getInheritedPrivateFields(Class<?> type) {
        List<Field> result = new ArrayList<Field>();
    
        Class<?> i = type;
        while (i != null && i != Object.class) {
            for (Field field : i.getDeclaredFields()) {
                if (!field.isSynthetic()) {
                    result.add(field);
                }
            }
            i = i.getSuperclass();
        }
    
        return result;
    }
    
        4
  •  20
  •   Community Mohan Dere    9 年前
    public static Field getField(Class<?> clazz, String fieldName) {
        Class<?> tmpClass = clazz;
        do {
            try {
                Field f = tmpClass.getDeclaredField(fieldName);
                return f;
            } catch (NoSuchFieldException e) {
                tmpClass = tmpClass.getSuperclass();
            }
        } while (tmpClass != null);
    
        throw new RuntimeException("Field '" + fieldName
                + "' not found on class " + clazz);
    }
    

    (基于 this

        5
  •  15
  •   benzen    15 年前

    事实上,我使用一个复杂的类型层次结构,所以你的解决方案是不完整的。 我需要进行递归调用以获取所有私有继承字段。

     /**
     * Return the set of fields declared at all level of class hierachy
     */
    public Vector<Field> getAllFields(Class clazz) {
        return getAllFieldsRec(clazz, new Vector<Field>());
    }
    
    private Vector<Field> getAllFieldsRec(Class clazz, Vector<Field> vector) {
        Class superClazz = clazz.getSuperclass();
        if(superClazz != null){
            getAllFieldsRec(superClazz, vector);
        }
        vector.addAll(toVector(clazz.getDeclaredFields()));
        return vector;
    }
    
        6
  •  8
  •   mguymon    7 年前

    我需要为中的蓝图添加对继承字段的支持 Model Citizen . 我派生了这个方法,它对于检索类的字段+继承字段更为简洁。

    private List<Field> getAllFields(Class clazz) {
        List<Field> fields = new ArrayList<Field>();
    
        fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
    
        Class superClazz = clazz.getSuperclass();
        if(superClazz != null){
            fields.addAll(getAllFields(superClazz));
        }
    
        return fields;
    }
    
        7
  •  7
  •   palacsint    13 年前
    private static Field getField(Class<?> clazz, String fieldName) {
        Class<?> tmpClass = clazz;
        do {
            for ( Field field : tmpClass.getDeclaredFields() ) {
                String candidateName = field.getName();
                if ( ! candidateName.equals(fieldName) ) {
                    continue;
                }
                field.setAccessible(true);
                return field;
            }
            tmpClass = tmpClass.getSuperclass();
        } while ( clazz != null );
        throw new RuntimeException("Field '" + fieldName +
            "' not found on class " + clazz);
    }