Setting variables by name in Java

I want to implement something in Java along the following lines:

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 the variable is defined based on the variable name without hardcoded variable names and without using any other data structures. Is it possible?

+11


source to share


6 answers


Here's how you can implement setAttribute

with reflection (I 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);
}

      

+24


source


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

Specifically, the section "Changing Field Values" describes how to do what you would like to do.



I note that the author says, "This feature is extremely powerful and has no equivalent in other traditional languages." Of course, over the past ten years (the article was written in 1998), we have made great strides in dynamic languages. The above is fairly easy to do in Perl, Python, PHP, Ruby, etc. I suspect this is the direction you may have come from based on the eval tag.

+5


source


Also, check out BeanUtils , which can hide some of the complexities of using reflection from you.

+3


source


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

+1


source


The question is specific to ints, which is helpful, however here's something more general. This type of method is useful if you are loading String

field / field value pairs into views.

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

}

      

+1


source


You might want to cache some 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);
    }
}

      

0


source







All Articles