Invoking setText() through reflection only if an object has an specific annotaion

I'm trying to set the text of a number of different components (JButton, JLabel, etc...) through reflection. I'm also using annotations in the fields that I want to change later on.

For example, I have the following code:

public class MainWindow {

    @UsesTextChanger
    private JButton btn1;

    @UsesTextChanger
    private JLabel lb1;

    public void ChangeTexts() {

        for (Field field: MainWindow.class.getDeclaredFields()) {
            field.setAccessible(true);
            UsesTextChanger usesTextChanger = field.getAnnotation(UsesTextChanger.class);
            if (usesTextChanger != null){   

                try {
                    Method method = field.getType().getMethod("setText", new Class[]{String.class});
                    method.invoke(field, "my new text");

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }       
    }
}

I am getting the following exception:

java.lang.IllegalArgumentException: object is not an instance of declaring class

Is there a way to get the instance of this field so I can invoke the setText() method properly?

I also tried to take another approach by making a loop through all my components (The code only works in the first layer for now though), and actually the setText() works, however I don't know how to check if the annotation is there:

for (Component component: this.frame.getContentPane().getComponents()) {
    try {
        boolean componentUsesTextChangerAnnotation = true; // Is there a way to check if an annotation exists in an instanced object?
        if (componentUsesTextChangerAnnotation) {
            Method method = component.getClass().getMethod("setText", new Class[]{String.class});
            method.invoke(component, "my new text");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Thanks!

Jon Skeet
people
quotationmark

You're trying to call the method on the Field - whereas you actually want to call it on the value of the field within your object.

You want:

Method method = field.getType().getMethod("setText", String.class);
Object target = field.get(this);
method.invoke(target, "my new text");

(I've used the fact that Class.getMethod has a varargs parameter to simplify the call to that, btw.)

people

See more on this question at Stackoverflow