Access to private inherited fields via reflection in Java

JavaReflectionInheritancePrivate Members

Java Problem Overview


I found a way to get inherited members via class.getDeclaredFields(); and acces to private members via class.getFields() But i'm looking for private inherited fields. How can i achieve this?

Java Solutions


Solution 1 - Java

This should demonstrate how to solve it:

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

(Or Class.getDeclaredFields for an array of all fields.)

Output:

5

Solution 2 - Java

The best approach here is using the Visitor Pattern do find all fields in the class and all super classes and execute a callback action on them.


Implementation

Spring has a nice Utility class ReflectionUtils that does just that: it defines a method to loop over all fields of all super classes with a callback: ReflectionUtils.doWithFields()

Documentation:

> Invoke the given callback on all fields in the target class, > going up the class hierarchy to get all declared fields.

> Parameters:
> - clazz - the target class to analyze
> - fc - the callback to invoke for each field
> - ff - the filter that determines the fields to apply the callback to

Sample code:

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

Output:

> Found field private transient boolean javax.management.relation.RoleUnresolvedList.typeSafe in type class javax.management.relation.RoleUnresolvedList
> Found field private transient boolean javax.management.relation.RoleUnresolvedList.tainted in type class javax.management.relation.RoleUnresolvedList
> Found field private transient java.lang.Object[] java.util.ArrayList.elementData in type class java.util.ArrayList
> Found field private int java.util.ArrayList.size in type class java.util.ArrayList
> Found field protected transient int java.util.AbstractList.modCount in type class java.util.AbstractList

Solution 3 - Java

This'll do it:

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

If you use a code coverage tool like EclEmma, you have to watch out: they add a hidden field to each of your classes. In the case of EclEmma, these fields are marked synthetic, and you can filter them out like this:

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

Solution 4 - Java

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

(based on this answer)

Solution 5 - Java

In fact i use a complex type hierachy so you solution is not complete. I need to make a recursive call to get all the private inherited fields. Here is my solution

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

Solution 6 - Java

I needed to add support for inherited fields for blueprints in Model Citizen. I derived this method that is a bit more concise for retrieving a Class' fields + inherited fields.

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

Solution 7 - Java

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbenzenView Question on Stackoverflow
Solution 1 - JavaaioobeView Answer on Stackoverflow
Solution 2 - JavaSean Patrick FloydView Answer on Stackoverflow
Solution 3 - JavajqnoView Answer on Stackoverflow
Solution 4 - JavaExterminator13View Answer on Stackoverflow
Solution 5 - JavabenzenView Answer on Stackoverflow
Solution 6 - JavamguymonView Answer on Stackoverflow
Solution 7 - JavaKenny CasonView Answer on Stackoverflow