1

我有一个带有几个不同字符串字段(标题、作者、主题...)的 Book 对象,并且我正在设计一个 GUI 来显示书籍集合中的每个字段。我有一个面板,对于每个字段,我想要一个标签(命名字段)、一个 TextField(显示存储在该字段中的值)和一个编辑按钮,它使 TextField 可编辑并显示第二个按钮保存所做的任何编辑。

我不想将这些中的每一个单独编码到面板中,而是创建一个带有单个标签、TextField 和按钮的“字段面板”。然后我想使用 foreach 循环为每个字段(存储在列表中)创建这些面板之一并将这些面板加载到主面板中。

我知道以下是不可能的:

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);
}

但是有没有另一种方法来实现我在最后一行尝试做的事情,即使用命名的字符串变量来引用对象的字段?换句话说,我想做:(objectInstance.stringVariable其中 stringVariable 匹配 objectInstance 的字段名称。

4

1 回答 1

3

你在寻找反思。有一个关于该主题的Java 教程可以帮助您入门,然后有很多很多库可以使反射更容易,例如Commons BeanUtils和Spring 的 util 包中的几个类。几乎所有的框架都会在其中包含某种反射辅助类,因为直接使用反射非常麻烦。

作为您的案例的快速示例,使用Commons BeanUtils.getProperty(),您可以说:

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

这是一个以手动方式执行此操作的完整示例,因此您可以了解它是如何适应的:

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();
    }
}
于 2013-03-04T17:11:31.847 回答