Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/368.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中通过反射访问私有继承字段_Java_Reflection_Inheritance_Private Members - Fatal编程技术网

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

在Java中通过反射访问私有继承字段,java,reflection,inheritance,private-members,Java,Reflection,Inheritance,Private Members,我找到了一种通过class.getDeclaredFields()获取继承成员的方法 并通过class.getFields() 但我在找私人继承的领域。 如何实现此目标?这应该说明如何解决此问题: import java.lang.reflect.Field; class Super { private int i = 5; } public class B extends Super { public static void main(String[] args) thro

我找到了一种通过
class.getDeclaredFields()获取继承成员的方法
并通过
class.getFields()
但我在找私人继承的领域。
如何实现此目标?

这应该说明如何解决此问题:

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));
    }
}
(或用于所有字段的数组。)

输出:

5

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

 /**
 * 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;
}
/**
*返回在类层次结构的所有级别声明的字段集
*/
公共向量getAllFields(clazz类){
返回getAllFieldsRec(clazz,new Vector());
}
私有向量getAllFieldsRec(类clazz,向量向量){
类superClazz=clazz.getSuperclass();
if(超级杯!=null){
getAllFieldsRec(超级Lazz,矢量);
}
addAll(toVector(clazz.getDeclaredFields());
返回向量;
}
这样就可以了:

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;
}
私有列表getInheritedPrivateFields(类类型){
列表结果=新建ArrayList();
i类=类型;
而(i!=null&&i!=Object.class){
Collections.addAll(result,i.getDeclaredFields());
i=i.getSuperclass();
}
返回结果;
}
如果您使用这样的代码覆盖工具,您必须小心:它们会为您的每个类添加一个隐藏字段。在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;
}
私有列表getInheritedPrivateFields(类类型){
列表结果=新建ArrayList();
i类=类型;
而(i!=null&&i!=Object.class){
for(字段:i.getDeclaredFields()){
如果(!field.isSynthetic()){
结果。添加(字段);
}
}
i=i.getSuperclass();
}
返回结果;
}

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


实施 Spring有一个很好的实用程序类,它就是这样做的:它定义了一个方法,通过回调循环所有超类的所有字段:

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

参数:
-clazz-要分析的目标类
-fc-为每个字段调用的回调
-ff-确定要应用回调的字段的筛选器

示例代码: 输出: 在类型类javax.management.relation.RoleUnresolvedList中找到字段private transient boolean javax.management.relation.RoleUnresolvedList.typeSafe
在类型类javax.management.relation.RoleUnresolvedList中找到了受污染的字段私有临时布尔javax.management.relation.RoleUnresolvedList
在类型类java.util.ArrayList中找到字段private transient java.lang.Object[]java.util.ArrayList.elementData
在类型类java.util.ArrayList中找到字段private int java.util.ArrayList.size
在类型类java.util.AbstractList中找到受字段保护的瞬态int java.util.AbstractList.modCount

私有静态字段getField(类clazz,字符串fieldName){
类别tmpClass=clazz;
做{
for(字段:tmpClass.getDeclaredFields()){
字符串candidateName=field.getName();
如果(!candidateName.equals(fieldName)){
继续;
}
字段。setAccessible(true);
返回字段;
}
tmpClass=tmpClass.getSuperclass();
}while(clazz!=null);
抛出新的RuntimeException(“字段“”+fieldName+
“‘未在类上找到’+clazz);
}
公共静态字段getField(类clazz,字符串fieldName){
类别tmpClass=clazz;
做{
试一试{
字段f=tmpClass.getDeclaredField(字段名);
返回f;
}捕获(无此字段例外){
tmpClass=tmpClass.getSuperclass();
}
}while(tmpClass!=null);
抛出新的RuntimeException(“字段“”+fieldName
+“‘未在类上找到’+clazz);
}

(基于答案)

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

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;
}
私有列表getAllFields(类clazz){
列表字段=新的ArrayList();
addAll(Arrays.asList(clazz.getDeclaredFields());
类superClazz=clazz.getSuperclass();
if(超级杯!=null){
addAll(getAllFields(superClazz));
}
返回字段;
}

“私有继承字段”不存在。如果一个字段是私有的,它不会被继承,并且只保留在父类的范围内。要访问父私有字段,您必须首先访问父类(参见aioobe的回答),也就是说,受保护的字段是继承的,但您也必须这样做才能通过反射获得它们。然而,他的解决方案可能会重复,不是吗?Vector是糟糕的旧代码。请使用集合框架中的当前数据结构(ArrayList在大多数情况下是足够的)@aperkins aioobe的答案看起来像我的,但我找到了,然后我看到了答案@seanizer Vector并没有那么古老,它是集合API的一个成员“从Java2平台v1.2开始,这个类已经被改造为实现List,所以它成为Java集合框架的一部分。”在1.2中被改造?如果那不是旧的,那是什么?资料来源:Vector的开销很大,因为所有内容都是同步的。在需要同步的地方,java.util.concurrent中有更好的类。Vector、Hashtable和StringBuffer在大多数情况下都应该被ArrayList、HashMap和StringBuilder替换感谢您对合成字段的评论,EMMA也这么做
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);
}
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);
}
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;
}