views:

863

answers:

5

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?

+5  A: 

In general, you want to use Reflection. Here is a good introduction to the topic with examples: http://java.sun.com/developer/technicalArticles/ALT/Reflection/index.html

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.

Greg Hewgill
+2  A: 

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

toolkit
+5  A: 

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);
}
Chris Jester-Young
A: 

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);
    }
}
Frank Krueger
Why bother when the reflection layer already does this caching? Read the source code for java.lang.Class and see for yourself; it even handles invalidating the cache when a class gets reloaded.
Chris Jester-Young
+1  A: 

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

PhiLho