81

I am making university project.
I need to get all fields from class. Even private and inherited. I tried to get all declared fields and then cast to super class and repeat. Fragment of my code:

private void listAllFields(Object obj) {
    List<Field> fieldList = new ArrayList<Field>();
    while (obj != null) {
        fieldList.addAll(Arrays.asList(obj.getClass().getDeclaredFields()));
        obj = obj.getClass().getSuperclass().cast(obj);
    }
    // rest of code

But it does not work. tmpObj after casting is still the same class (not superclass).
I will appreciate any help how to fix casting problem, or how to retrieve these fields in different way.

Problem is not to gain access to fields, but to get names of fields!
I manages it that way:

private void listAllFields(Object obj) {
    List<Field> fieldList = new ArrayList<Field>();
    Class tmpClass = obj.getClass();
    while (tmpClass != null) {
        fieldList.addAll(Arrays.asList(tmpClass .getDeclaredFields()));
        tmpClass = tmpClass .getSuperclass();
    }
    // rest of code
Neuron
  • 5,141
  • 5
  • 38
  • 59
Michał Herman
  • 3,437
  • 6
  • 29
  • 43
  • To get all inherited fields, you must use recursion, as described [here](http://stackoverflow.com/questions/1042798/retrieving-the-inherited-attribute-names-values-using-java-reflection) – Dmitry Kuskov Apr 30 '13 at 09:15
  • @DmitryKuskov You can't use that notation in comments. You have to use `[label](url)`. – maba Apr 30 '13 at 09:16
  • Possible duplicate of [Retrieving the inherited attribute names/values using Java Reflection](https://stackoverflow.com/questions/1042798/retrieving-the-inherited-attribute-names-values-using-java-reflection) – Vadzim May 28 '19 at 13:14

9 Answers9

96
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)

Neuron
  • 5,141
  • 5
  • 38
  • 59
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • Does not work for me, I want to get field value from superclass and here I get Class object. – Sarz Apr 23 '21 at 07:48
51

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

ahmed hamdy
  • 5,096
  • 1
  • 47
  • 58
Tom McIntyre
  • 3,620
  • 2
  • 23
  • 32
25

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;
    }
Adelin
  • 18,144
  • 26
  • 115
  • 175
6

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
    );
}
Chris K
  • 11,622
  • 1
  • 36
  • 49
4

try these

How do I read a private field in Java?

Is it possible in Java to access private fields via reflection

Field.setAccessible(true) is what you have to do to make it accessible via reflection

import java.lang.reflect.Field;

class B 
{
    private int i = 5;
}

public class A extends B 
{
    public static void main(String[] args) throws Exception 
    {
        A a = new A();
        Field[] fs = a.getClass().getSuperclass().getDeclaredFields();
        for (Field field : fs)
        {
            field.setAccessible(true);
            System.out.println( field.get( a ) );
        }
    }
}
Community
  • 1
  • 1
gurvinder372
  • 66,980
  • 10
  • 72
  • 94
  • I do not know names of fields - This have to be generic solution. I know that I can make field accessible, but first I have to know name of parent private field. I my problem is to get that name, not to access it when I have it. – Michał Herman Apr 30 '13 at 09:03
  • For private fields you need to know the names and for inherited use getSuperclass() method – Vineet Singla Apr 30 '13 at 09:06
  • You simply need to run through all the declaredfields like this http://stackoverflow.com/questions/3567372/access-to-private-inherited-fields-via-reflection-in-java – gurvinder372 Apr 30 '13 at 09:10
2

To get superclass fields use getSuperclass(). From there you can get fields of superclass.

Vineet Singla
  • 1,609
  • 2
  • 20
  • 34
0

You have to set setAccessible to true before extracting the value. Sometime JVM does not allow to extract the private variable, it may give Security Exception.

ClassName obj  =  new ClassName();
Field field  =   ClassName.class.getDeclaredField  ("name of the field");
field.setAccessible   (true);
DataType value  =  (DataType) field.get  (obj);
Brane
  • 3,257
  • 2
  • 42
  • 53
  • getDeclaredField is not going to fetch the inherited members. The answers at the top mentioned about looping through all the superclasses is the exact approach. This will only list the member variables of the same class. – KnockingHeads Jul 28 '21 at 14:12
0

Previously asked.

Access to private inherited fields via reflection in Java

In your code, set field.setAccessible(true);

Community
  • 1
  • 1
Maximin
  • 1,655
  • 1
  • 14
  • 32
-1

HERE IS A SOLUTION

//My object

    Student student =new Student();

    Field[] field2=student.getClass().getSuperclass().getDeclaredFields();
    Field[] field1=student.getClass().getDeclaredFields();
    
    Field [] all_Fields=new Field[field1.length+field2.length];
    
    
    //Joining field 1 and two
      System.arraycopy(field2, 0, all_Fields, 0, field2.length);
      System.arraycopy(field1, 0, all_Fields, field2.length, field1.length);
    

      //Printing all fields
    for(Field i:all_Fields)
    {
        System.out.println(i);
    }

//If you want to get fields from multiple SuperClasses then you can iterate using the following code:

    Class clazz = Student.class;
    while (clazz != null) {
      clazz= clazz.getSuperclass(); 
    }
Stones
  • 1
  • 1
  • 2
    This does not work if a class has multiple levels of inheritance – sina Sep 17 '20 at 15:07
  • If the super class inherits another class, you can still get the super class's inherited class fields, by iterating over the super classes. here is code: Class clazz = Student.class; while (clazz != null) { System.out.println(clazz.getName()); clazz= clazz.getSuperclass(); } – Stones Sep 18 '20 at 20:01
  • 1
    I know that, but someone copying your example code might not. As the original question asked for all inherited fields, your solution currently does not answer the question. Maybe you could edit the code a bit to reflect that. – sina Sep 20 '20 at 17:16