mercredi 10 mai 2023

Calling java.lang.reflect.Field::getValue(this) from abstract superclass defined method returns IllegalAccessException

I'm trying to print the whole hierarchy of a class using reflection.

To do this I defined an abstract superclass A that defines the toString(int offset) method:

abstract class A {
    public String toString(int offset) {
        StringBuilder builder = new StringBuilder();
        try {
            for (Field field : this.getClass().getDeclaredFields()) {
                builder.append(String.join("", Collections.nCopies(offset, "\t")));
                builder.append(field.getName()).append(": ");
                field.setAccessible(true); // workaround
                if (field.getType().isPrimitive()) {
                    // (int, float, ...)
                    builder.append(field.get(this));
                } else if (field.getType().getName().contains("java.lang")) {
                    // (Integer, String, ...)
                    builder.append(field.get(this).toString());
                } else {
                    // Other classes
                    builder.append("\n").append(A.class.cast(field.get(this)).toString(offset + 1));
                }
                builder.append("\n");
                field.setAccessible(false); // workaround
            }
        } catch (Exception e) {
            System.out.print(e);
        }
        return builder.toString();
    }
}

then I have some classes that extend the A class:

public class X extends A {
    private String field1;
    private Y field2;
}

public class Y extends A {
    private String field3;
    private String field4;
}

which instances contains some values.

The expected output of the call x.toString(0) should be:

field1: value1
field2:
    field3: value3
    field4: value4

Without the use of field.setAccessible(true) when I call x.toString(0) I get

IllegalAccessException: Class A can not access a member of class X with modifiers "private"

but I cannot undestand why.

When I check the reference while debugging this refers to X.class, so why the field.getValue(this) doesn't work?

Shouldn't this refer to the instance of the class calling the method? Am I missing something?





Aucun commentaire:

Enregistrer un commentaire