问题

我找到了一种方法来获取继承成员viaclass.getDeclaredFields();和访问私人成员viaclass.getFields()但我正在寻找私有继承的字段。我怎样才能做到这一点?


#1 热门回答(113 赞)

这应该演示如何解决它:

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[] fs = b.getClass().getSuperclass().getDeclaredFields();
        fs[0].setAccessible(true);
        System.out.println(fs[0].get(b));
    }
}

输出:

5

#2 热门回答(37 赞)

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

##实施

Spring有一个很好的Utility classReflectionUtils就是这样:它定义了一个循环遍历所有超类的所有字段并使用回调的方法:ReflectionUtils.doWithFields()

##文档:

在目标类的所有字段上调用给定的回调,上升类层次结构以获取所有声明的字段。参数: - clazz - 要分析的目标类 - fc - 为每个字段调用的回调 - 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中找到字段private transient boolean javax.management.relation.RoleUnresolvedList.typeSafe找到字段private transient boolean javax.management.relation.RoleUnresolvedList.tainted类型类javax.management.relation.RoleUnresolvedList Found字段私有瞬态java.lang.Object [] java.util.ArrayList.elementData类型类java.util.ArrayList找到字段private int java.util.ArrayList.size类型类java.util.ArrayList找到字段protected transient int java类型为java.util.AbstractList的.util.AbstractList.modCount


#3 热门回答(28 赞)

这样做:

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;
}

原文链接