17

我希望在 Java 中实现一些东西:

class Foo{
 private int lorem; //
 private int ipsum;      

 public setAttribute(String attr, int val){
  //sets attribute based on name
 }

 public static void main(String [] args){
  Foo f = new Foo();
  f.setAttribute("lorem",1);
  f.setAttribute("ipsum",2);
 }

 public Foo(){}
}

...其中一个变量是基于变量名设置的,没有硬编码的变量名,也没有使用任何其他数据结构。这可能吗?

4

6 回答 6

34

以下是setAttribute使用反射实现的方法(我已经重命名了函数;对于不同的字段类型有不同的反射函数):

public void setIntField(String fieldName, int value)
        throws NoSuchFieldException, IllegalAccessException {
    Field field = getClass().getDeclaredField(fieldName);
    field.setInt(this, value);
}
于 2008-11-09T22:22:54.257 回答
5

通常,您希望使用反射。这是一个很好的主题介绍和例子

特别是,“更改字段值”部分描述了如何做您想做的事情。

我注意到作者说,“这个功能非常强大,在其他传统语言中是没有的。” 当然,在过去的十年里(这篇文章写于 1998 年),我们已经看到动态语言取得了长足的进步。上面的内容在 Perl、Python、PHP、Ruby 等中很容易完成。我怀疑这是您基于“eval”标签可能来自的方向。

于 2008-11-09T22:17:06.437 回答
4

另外,看看BeanUtils可以隐藏使用反射的一些复杂性。

于 2008-11-09T22:21:26.193 回答
3

这个问题是特定于整数的,这很有帮助,但是这里有一些更笼统的东西。String如果您正在加载字段名称/字段值对的表示形式,这种类型的方法很有用。

import java.lang.reflect.Field;

public class FieldTest {

    static boolean isValid = false;
    static int count = 5;

    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        FieldTest test = new FieldTest();
        test.setProperty("count", "24");
        System.out.println(count);
        test.setProperty("isValid", "true");
        System.out.println(isValid);
    }

    public void setProperty(String fieldName, String value) throws NoSuchFieldException, IllegalAccessException {
        Field field = this.getClass().getDeclaredField(fieldName);
        if (field.getType() == Character.TYPE) {field.set(getClass(), value.charAt(0)); return;}
        if (field.getType() == Short.TYPE) {field.set(getClass(), Short.parseShort(value)); return;}
        if (field.getType() == Integer.TYPE) {field.set(getClass(), Integer.parseInt(value)); return;}
        if (field.getType() == Long.TYPE) {field.set(getClass(), Long.parseLong(value)); return;}
        if (field.getType() == Float.TYPE) {field.set(getClass(), Float.parseFloat(value)); return;}
        if (field.getType() == Double.TYPE) {field.set(getClass(), Double.parseDouble(value)); return;}
        if (field.getType() == Byte.TYPE) {field.set(getClass(), Byte.parseByte(value)); return;}
        if (field.getType() == Boolean.TYPE) {field.set(getClass(), Boolean.parseBoolean(value)); return;}
        field.set(getClass(), value);
    }

}
于 2015-05-18T18:16:39.387 回答
1

根据使用情况,您可以按照上面的建议使用反射,或者 HashMap 可能更适合...

于 2008-11-10T09:43:49.247 回答
-1

您可能希望在使用时缓存一些反射数据:

import java.lang.reflect.Field;
import java.util.HashMap;

class Foo {
    private HashMap<String, Field> fields = new HashMap<String, Field>();

    private void setAttribute(Field field, Object value) {
        field.set(this, value);
    }

    public void setAttribute(String fieldName, Object value) {
        if (!fields.containsKey(fieldName)) {
            fields.put(fieldName, value);
        }
        setAttribute(fields.get(fieldName), value);
    }
}
于 2008-11-09T23:16:14.553 回答