使用String变量来引用对象字段

时间:2013-03-04 17:08:48

标签: java reflection

我有一个Book对象,其中有几个不同的String字段(标题,作者,主题......),我设计了一个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);
}

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

1 个答案:

答案 0 :(得分:3)

你正在寻找反思。这个主题上有一个Java tutorial可以帮助您入门,然后有很多很多库可以让反思变得更容易,例如Commons BeanUtilsSpring's util package中的几个类。几乎任何框架都会有一些反射辅助类,因为直接使用反射它会非常混乱。

作为您案例的简单示例,使用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();
    }
}