在Java中按名称设置变量

发布于 2024-07-08 11:10:18 字数 398 浏览 7 评论 0 原文

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

...其中变量是根据变量名称设置的,无需对变量名称进行硬编码,也不使用任何其他数据结构。 这可能吗?

I'm looking to implement something in Java along the lines of:

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(){}
}

...where a variable is set based on the variable name without the variable names hard-coded and without using any other data structures. Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

澜川若宁 2024-07-15 11:10:18

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

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

Here's how you might implement setAttribute using reflection (I've renamed the function; there are different reflection functions for different field types):

public void setIntField(String fieldName, int value)
        throws NoSuchFieldException, IllegalAccessException {
    Field field = getClass().getDeclaredField(fieldName);
    field.setInt(this, value);
}
命比纸薄 2024-07-15 11:10:18

一般来说,您想要使用反射。 这是对 带有示例的主题

特别是,“更改字段值”部分描述了如何执行您想要执行的操作。

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

In general, you want to use Reflection. Here is a good introduction to the topic with examples

In particular, the "Changing Values of Fields" section describes how to do what you'd like to do.

I note that the author says, "This feature is extremely powerful and has no equivalent in other conventional languages." Of course, in the last ten years (the article was written in 1998) we have seen great strides made in dynamic languages. The above is fairly easily done in Perl, Python, PHP, Ruby, and so on. I suspect this is the direction you might have come from based on the "eval" tag.

妞丶爷亲个 2024-07-15 11:10:18

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

Also, take a look at BeanUtils which can hide some of the complexity of using reflection from you.

夏见 2024-07-15 11:10:18

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

}

The question is specific to ints, which is helpful, however here is something a bit more general. This type of method is useful if you are loading in String representations of field name / field value pairs.

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

}
计㈡愣 2024-07-15 11:10:18

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

Depending on the usage, you can use reflection as advised above, or perhaps a HashMap would be better suited...

雨后咖啡店 2024-07-15 11:10:18

您可能希望在执行此操作时缓存一些反射数据:

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

You might want to cache some of the reflection data while you're at it:

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文