dimanche 18 juin 2017

How to change information of objects in a List with reflection?

I would like to read and manipulate the information from a List field. More specific, I would like to access the getter and setter of the nested List objects listedInnerClasses and hashMappedInnerClasses. I have hardly influence of the objects given into my observeAndReflect method. I don't know which Class will be passed into in the future.

public class ReflectMe {

private int id;
private long speed = 10;
private SimpleInnerClass simpleInnerClass;
private List<ListedInnerClass> listedInnerClasses;
private HashMap<Long, HashMappedInnerClass> hashMappedInnerClass;
// ... getter and setter
}

public class ListedInnerClass {

private long id;
private String foo = "bar";
// ... getter and setter
}

I filled in some stuff to test:

private void start() {

    // reflectionTest
    ReflectMe me = new ReflectMe();
    List<ListedInnerClass> listedInnerClasses = new ArrayList<ListedInnerClass>();
    ListedInnerClass aClass1 = new ListedInnerClass();
    ListedInnerClass aClass2 = new ListedInnerClass();
    aClass2.setFoo("bla");
    listedInnerClasses.add(aClass1);
    listedInnerClasses.add(aClass2);
    me.setListedInnerClasses(listedInnerClasses);
    try {
        observeAndReflect(me);
    } catch(IllegalAccessException e) {
        logger.error(e);
    }
}

And then I tried to get access. I started with the List:

private void observeAndReflect(Object o) throws IllegalAccessException {

    for (Field field : o.getClass().getDeclaredFields()) {
        field.setAccessible(true);
        Class<?> fieldType = field.getType();

        logger.info("# Type: " + fieldType.getName() + " getName: " + field.getName() + " getValue " + field.get(o));

        if (fieldType == List.class) {
            // here I would like to change information of the lists objects
            logger.info("## My List: " + field.get(o));
            observeAndReflect(field.get(o));
        }
    }
}

My logoutput gives me some information:

INFO [main] (Runner.java:136) - # Type: int getName: id getValue 0
INFO [main] (Runner.java:136) - # Type: long getName: speed getValue 10
INFO [main] (Runner.java:136) - # Type: application.SimpleInnerClass getName: simpleInnerClass getValue null
INFO [main] (Runner.java:136) - # Type: java.util.List getName: listedInnerClasses getValue [application.ListedInnerClass@7bc1a03d, application.ListedInnerClass@70b0b186]
INFO [main] (Runner.java:139) - ## My List: [application.ListedInnerClass@7bc1a03d, application.ListedInnerClass@70b0b186]
INFO [main] (Runner.java:136) - # Type: long getName: serialVersionUID getValue 8683452581122892189
...

But I fail to get access to the information in my List.

As far as I understand, the information of the type parameter from the List gets lost due to type erasure. So the compiler does know there is a List, but forgets that there are objects of the Type ListedInnerClass in. I tried to reconvert that object but always ended up with the same problem: no access to getters and setters.

Is there still a way to get access to the information?

Thanks in advance!





Aucun commentaire:

Enregistrer un commentaire