Get all fields (even private and inherited) from class
getDeclaredFields()
gives you all fields on that Class, including private
ones.
getFields()
gives you all public
fields on that Class AND it's superclasses.
If you want private
/ protected
methods of Super Classes, you will have to repeatedly call getSuperclass()
and then call getDeclaredFields()
on the Super Class object.
Nothing here isn't clearly explained in the javadocs
obj = obj.getClass().getSuperclass().cast(obj);
This line does not do what you expect it to do. Casting an Object
does not actually change it, it just tells the compiler to treat it as something else.
E.g. you can cast a List
to a Collection
, but it will still remain a List
.
However, looping up through the super classes to access fields works fine without casting:
Class<?> current = yourClass;
while(current.getSuperclass()!=null){ // we don't want to process Object.class
// do something with current's fields
current = current.getSuperclass();
}
BTW, if you have access to the Spring Framework, there is a handy method for looping through the fields of a class and all super classes:ReflectionUtils.doWithFields(baseClass, FieldCallback)
(also see this previous answer of mine: Access to private inherited fields via reflection in Java)
Here is the method I use to get all the fields of an object
private <T> List<Field> getFields(T t) {
List<Field> fields = new ArrayList<>();
Class clazz = t.getClass();
while (clazz != Object.class) {
fields.addAll(Arrays.asList(clazz.getDeclaredFields()));
clazz = clazz.getSuperclass();
}
return fields;
}
This solution uses Java 8 streams, useful for those who are learning functional programming in Java. It iterates over getSuperclass and getDeclaredFields as per the other answers, but it does so in a functional way.
The following line will print the name of each field name found on SomeClass or any of its superclasses.
allFieldsFor(SomeClass.class).map(Field::getName).forEach(System.out::println);
Here is the code that steps through the superclasses to create the stream of fields.
private Stream<Field> allFieldsFor( Class c ) {
return walkInheritanceTreeFor(c).flatMap( k -> Arrays.stream(k.getDeclaredFields()) );
}
private Stream<Class> walkInheritanceTreeFor( Class c ) {
return iterate( c, k -> Optional.ofNullable(k.getSuperclass()) );
}
The following method is modelled from Streams.iterate, however Streams.iterate is designed to create infinite streams. This version has been modified to end when Optional.none() is returned from the fetchNextFunction.
private <T> Stream<T> iterate( T seed, Function<T,Optional<T>> fetchNextFunction ) {
Objects.requireNonNull(fetchNextFunction);
Iterator<T> iterator = new Iterator<T>() {
private Optional<T> t = Optional.ofNullable(seed);
public boolean hasNext() {
return t.isPresent();
}
public T next() {
T v = t.get();
t = fetchNextFunction.apply(v);
return v;
}
};
return StreamSupport.stream(
Spliterators.spliteratorUnknownSize( iterator, Spliterator.ORDERED | Spliterator.IMMUTABLE),
false
);
}