Java Reflection - Accessing Fields of a Field

2019-08-23 17:03发布

问题:

Suppose I have the class

class car
{
       int color = 1;
       seats carSeats = new seats();

       class seats
       {
              int numSeats = 4;
       }
}

Using Java reflection, I can use the following:

car c = new car();
Field[] carFields = c.getClass().getDeclaredFields();

carFields would have { color, carSeats } as the fields. The instance, carSeats, has another field called numSeats.

Technically, I should be able to do another getFields() operation such that:

Field[] seatFields = carFields[1].getClass().getDeclaredFields();

But I am given garbage data (DECLARED, PUBLIC?) Why so? Does Java reflection not work for inner classes?

回答1:

carFields[1].getClass() is going to represent a Field object. You want carFields[1].getType().getDeclaredFields().

Also, as BalusC commented, be careful. The fields aren't necessarily in the order you expect.



回答2:

Here is a short snippet that can give some hints on Reflection

import java.lang.reflect.Field;

public class Car {

int color = 1;
int wheels = 4;
Seats carSeats = new Seats();

class Seats {
    int numSeats = 4;
}

public static void printFields(Field[] fields, Object o) {
    System.out.println(o.getClass());
    try {
        for (int i = 0; i < fields.length; i++) {
            Field f = fields[i];
            f.setAccessible(true);
            System.out.println(f.getName() + " " + 
                    f.getType().getName()  + " " + 
                    f.get(o));

        }
    } catch (IllegalArgumentException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

public static void main(String args[]) {
    Car car = new Car();
    Class<?>[] classes = Car.class.getDeclaredClasses();

    printFields(Car.class.getDeclaredFields(), car);
    for (int i = 0; i < classes.length; i++) {
        Class<?> klass = classes[i];
        printFields(klass.getDeclaredFields(), car.carSeats);
    }
}

}

I find it good fun to use write code that uses reflection, but really hard to trouble shoot...



回答3:

You could use Traverser class of java-util library which traverse every field of a class with the support of nested fields, which is what you want.

Traverser - Pass any Java object to this Utility class, it will call your passed in anonymous method for each object it encounters while traversing the complete graph. It handles cycles within the graph. Permits you to perform generalized actions on all objects within an object graph.