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?
-
28"private inherited fields" does not exist. If a field is private, it is not inherited, and remains only to the scope of the parent class. To access parent private fields, you have to access parent class first (cf. aioobe's response)Benoit Courtine– Benoit Courtine08/25/2010 15:22:58Commented Aug 25, 2010 at 15:22
-
6that said, protected fields are inherited, but you have to do the same to get them by reflection.Bozho– Bozho08/25/2010 16:14:26Commented Aug 25, 2010 at 16:14
-
Possible duplicate of Retrieving the inherited attribute names/values using Java ReflectionVadzim– Vadzim05/28/2019 13:04:29Commented May 28, 2019 at 13:04
8 Answers 8
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
-
Does this get all superclasses' fields or just the direct superclass?NeoZoom.lua– NeoZoom.lua05/14/2019 16:28:17Commented May 14, 2019 at 16:28
-
Direct super classes' fields. You can recurse on
getSuperclass()
until you reachnull
if you want to go higher.aioobe– aioobe05/14/2019 17:11:03Commented May 14, 2019 at 17:11 -
Why don't you use
getDeclaredFields()[0]
orgetDeclaredField("i")
but rather repeat the[0]
array access in the next two statements?Holger– Holger12/03/2019 15:41:04Commented Dec 3, 2019 at 15:41 -
It's due to the way this particular question is formulated. It was basically just a demonstration of how to use
getDeclaredFields
. Answer has been updated.aioobe– aioobe12/03/2019 15:47:35Commented Dec 3, 2019 at 15:47
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
-
4that is not a "visitor pattern", but it is still a very nice tool if you have the Spring virus in your code. thanks for sharing it :)thinlizzy– thinlizzy08/28/2013 00:27:12Commented Aug 28, 2013 at 0:27
-
3@jose.diego I'm pretty sure you could argue about that. It visits a class hierarchy rather than an object tree, but the principle remains the sameSean Patrick Floyd– Sean Patrick Floyd08/28/2013 14:43:41Commented Aug 28, 2013 at 14:43
-
Not sure if this comment will get a response, but you're only visiting a particular field at a time with this solution. If I need to look at other fields at the same time -- e.g., set this field to "abc" if another field is NULL -- I don't have the object as a whole available to me.gene b.– gene b.11/25/2016 19:25:07Commented Nov 25, 2016 at 19:25
-
Its too bad that the JavaDoc for this class indicates that "it is only intended for internal use", so this is a possible risk to anyone who wishes to use it.spaceman spiff– spaceman spiff07/09/2018 04:07:21Commented Jul 9, 2018 at 4:07
-
1@spacemanspiff you're technically correct, but this class has been around for about 15 years (including 4 major release versions) and has widely been used by many Spring customers. I doubt they'll pull it back now.Sean Patrick Floyd– Sean Patrick Floyd07/09/2018 16:31:19Commented Jul 9, 2018 at 16:31
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;
}
-
Thanks for your remark about synthetic fields, EMMA does the same.Anatoliy– Anatoliy05/22/2012 09:04:03Commented May 22, 2012 at 9:04
-
this gets declared and inherited fields of the argument class so should be named getDeclaredAndInheritedPrivateFields. perfect though thanks!Peter Hawkins– Peter Hawkins01/07/2013 19:58:27Commented Jan 7, 2013 at 19:58
-
1nice catch on the isSynthetic :)Lucas Crawford– Lucas Crawford11/03/2015 03:59:26Commented Nov 3, 2015 at 3:59
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)
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 static List<Field> getAllFields(Class<?> clazz) {
return getAllFieldsRec(clazz, new ArrayList<>());
}
private static List<Field> getAllFieldsRec(Class<?> clazz, List<Field> list) {
Class<?> superClazz = clazz.getSuperclass();
if (superClazz != null) {
getAllFieldsRec(superClazz, list);
}
list.addAll(Arrays.asList(clazz.getDeclaredFields()));
return list;
}
-
However, his solution did get you on the right path, didn't it?aperkins– aperkins08/25/2010 15:55:42Commented Aug 25, 2010 at 15:55
-
1Vector is bad old code. Please use a current data structure from the collections framework (ArrayList is adequate in most cases)Sean Patrick Floyd– Sean Patrick Floyd08/25/2010 15:58:45Commented Aug 25, 2010 at 15:58
-
@aperkins the answer of aioobe look like mine, but i found it and then i saw the answer. @seanizer Vector is not that old, and it'a a member of the collection APIbenzen– benzen08/25/2010 17:53:41Commented Aug 25, 2010 at 17:53
-
"As of the Java 2 platform v1.2, this class has been retrofitted to implement List, so that it becomes a part of Java's collection framework." retrofitted in 1.2? if that's not old then what is? Source: download.oracle.com/javase/1.4.2/docs/api/java/util/Vector.htmlSean Patrick Floyd– Sean Patrick Floyd08/25/2010 19:04:51Commented Aug 25, 2010 at 19:04
-
8Vector has a huge overhead because everything is synchronized. And where you need synchronization, there are better classes in java.util.concurrent. Vector, Hashtable and StringBuffer should in most cases be replaced by ArrayList, HashMap and StringBuilderSean Patrick Floyd– Sean Patrick Floyd08/25/2010 19:09:59Commented Aug 25, 2010 at 19:09
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);
}
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;
}
Commons Lang has the util method FieldUtils#getAllFieldsList
for this.
Explore related questions
See similar questions with these tags.