1

I have a Book object with several different String fields (title, author, subject...), and I am deigning a GUI to display each of these fields for a collection of books. I have a panel on which I want to have, for each field, a label (naming the field), a TextField (which displays the value stored in the field), and an edit button, which makes the TextField editable and displays a second button to save any edits made.

Rather than coding each of these into the panel individually, I would like to create a "field panel" with a single label, TextField and button. Then I want to use a foreach loop to create one of these panels for each field (stored in a list) and load these panels into the main panel.

I know that the following is not possible:

Book b = new Book();
String[] fieldTitles = {title, author, subject, publisher};
for (String str : fieldTitles) { 
    FieldPanel fp = new FieldPanel();
    fp.namelabel.settext(str);
    fp.textField.settext(b.str);
}

But is there another way to achieve what I'm trying to do here on the last line, which is to use a named String variable to refer to a field of an object? In other words, I want to do: objectInstance.stringVariable (where stringVariable matches the name of a field of the objectInstance.

2
  • 1
    With reflection and the class Field. Commented Mar 4, 2013 at 17:10
  • you can use reflections for that. but I wouldn't recommend it, because the compiler can't show you possible syntax errors that way Commented Mar 4, 2013 at 17:12

1 Answer 1

4

You're looking for reflection. There's a Java tutorial on the subject that will get you started, and then there are many, many libraries out there to make reflection easier, like Commons BeanUtils and several of the classes in Spring's util package. Pretty much any framework out there will have some kind of reflection helper class in it because it's so messy to work directly with reflection.

As a quick example for your case, using Commons BeanUtils.getProperty(), you could say:

fp.textField.settext((String) BeanUtils.getProperty(b, str));

Here's a complete example doing it the manual way so you can see how it fits in:

import java.lang.reflect.Field;

public class BasicReflectionGettingFieldValues {
    public static void main(String[] args) {
        FieldPanel fp = new FieldPanel();
        Book b = new Book("Mostly Harmless", "Douglas Adams");
        for (String str : Arrays.asList("author", "title")) {
            fp.namelabel.settext(str);
            fp.textField.settext(getField(b, str));
        }
    }

    private static String getField(Book b, String str) {
        try {
            Field field = Book.class.getDeclaredField(str);
            field.setAccessible(true);
            return (String) field.get(b);
        } catch (NoSuchFieldException e) {
            throw new IllegalStateException("Bad field name: " + str, e);
        } catch (IllegalAccessException e) {
            throw new IllegalStateException("Failed to access field " + str + " after making it accessible", e);
        }
    }

    static class Book {
        private String title;
        private String author;

        Book(String title, String author) {
            this.title = title;
            this.author = author;
        }
    }
    static class TextField {
        void settext(String s) {
            System.out.println("Setting text field to '" + s + "'");
        }
    }
    static class NameLabel {
        void settext(String s) {
            System.out.println("Setting name label to '" + s + "'");
        }
    }
    static class FieldPanel {
        private NameLabel namelabel = new NameLabel();
        private TextField textField = new TextField();
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Interesting. This is the subject we're supposed to be covering in my class this week. Would it be possible for you to give a me a brief sudocode example of how I could use reflection in this situation? It would help me wrap my head around a concept that I thus-far only understand in the abstract
So, in your BeanUtils example, b is the Book instance and str is the string used in the for loop? What would the ugly manual way look like? Thanks for the help!
Accidentally submitted the partial edit before. The manual way is there now :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.