我希望用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(){}
}

...其中基于变量名设置变量,而变量名称没有硬编码且不使用任何其他数据结构。这可能吗?

有帮助吗?

解决方案

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

public void setIntField(String fieldName, int value)
        throws NoSuchFieldException, IllegalAccessException {
    Field field = getClass().getDeclaredField(fieldName);
    field.setInt(this, value);
}

其他提示

通常,您希望使用Reflection。以下是主题与示例

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

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

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

问题是针对整数的,这是有帮助的,但这里有一些更一般的东西。如果要加载字段名称/字段值对的 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);
    }

}

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

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

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);
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top