Illegal access exception when trying to access attibrute from parent class by introspection

Raphael Jolivet picture Raphael Jolivet · Aug 13, 2010 · Viewed 9.9k times · Source

I am currently playing with introspection and annotations in Java 1.5. The have a parent abstract class AbstractClass. The inherited classes can have attributes (of type ChildClass) annotated with a custom @ChildAttribute annotation.

I wanted to write a generic method that would list all @ChildAttribute attributes of an instance.

Here is my code so far.

The parent class :

public abstract class AbstractClass {

    /** List child attributes (via introspection) */
    public final Collection<ChildrenClass> getChildren() {

        // Init result
        ArrayList<ChildrenClass> result = new ArrayList<ChildrenClass>();

        // Loop on fields of current instance
        for (Field field : this.getClass().getDeclaredFields()) {

            // Is it annotated with @ChildAttribute ?
            if (field.getAnnotation(ChildAttribute.class) != null) {
                result.add((ChildClass) field.get(this));
            }

        } // End of loop on fields

        return result;
    }
}

A test implementation, with some child attributes

public class TestClass extends AbstractClass {

    @ChildAttribute protected ChildClass child1 = new ChildClass();
    @ChildAttribute protected ChildClass child2 = new ChildClass();
    @ChildAttribute protected ChildClass child3 = new ChildClass();

    protected String another_attribute = "foo";

}

The test itself:

TestClass test = new TestClass();
test.getChildren()

I get the following error :

IllegalAccessException: Class AbstractClass can not access a member of class TestClass with modifiers "protected"

I tought that introspection access did not care about modifiers, and could read / write even private members.It seems that it is not the case.

How can I access the values of these attributes ?

Thanks in advance for your help,

Raphael

Answer

Kirk Woll picture Kirk Woll · Aug 13, 2010

Add field.setAccessible(true) before you get the value:

field.setAccessible(true);
result.add((ChildClass) field.get(this));