staticCoffee
staticCoffee

Reputation: 127

Check if class has a variable in its constructor based on a string?

Let's say I have a class named Person and its constructor had variables like name, age, hairColor and so on. If I had a function that receives a string that should match one of the class's variables, how could I check if that class actually had that variable and how could I go about modifying it? For example:

public class Person {
    public String name;
    public int age;
    public String hairColor;

    public Person() {
        name = "Bryce";
        age = 21;
        hairColor = "brown";
    }

    public void changeHairColor(String variable, String color) {
        if (/*this class contains the variable passed as an argument to this method*/) {
            // Person[variable] = color
        }
    }
}

I'm a python dev, mostly, so the method changeHairColor has some pseudo-python in it. I want to be able to edit the variable in a similar way you could edit variables inside of dictionaries with Python:

person = {
    "name": "Bryce",
    "age": 21,
    "hairColor": "brown"
}

def changeHairColor(variable, color):
    person[variable] = color

If that is at all possible.

Upvotes: 1

Views: 129

Answers (3)

Mick Mnemonic
Mick Mnemonic

Reputation: 7956

I would not solve this with reflection. If your PlayerCharacter has an enumerable set of attributes, I would model these as a Java enum and store the attribute values within the PlayerCharacter object in an EnumMap:

import java.util.EnumMap;

public class PlayerCharacter {

    public enum Attribute {
        AGILITY,
        DEXTERITY,
        /* etc ...*/
        VITALITY
    }

    private EnumMap<Attribute, Integer> attributes = new EnumMap<>(Attribute.class);

    public PlayerCharacter() {
        // initialize each attribute with a default value (0 in this example)
        for (Attribute a : Attribute.values()) {
            attributes.put(a, new Integer(0));
        }
    }

    public int getValue(Attribute attribute) {
       return attributes.get(attribute);
    }

    public void levelUp(Attribute attribute, int amount) {
        attributes.put(attribute, attributes.get(attribute) + amount);
    }
}

The biggest benefit of using an enum instead of plain old String (+reflection), is that this way you get compile-time type safety for the code that's using your PlayerCharacter.

Upvotes: 1

VHS
VHS

Reputation: 10184

Using Reflection API, you can access the methods and properties on an object at run time. The other answer describes its usage. But I don't recommend reflections for your problem. How about the following:

   public void changeHairColor(String variable, String color) {
       if("name".equalsIgnoreCase(variable))
           this.name = color;
       else if("age".equalsIgnoreCase(variable))
           this.age = Integer.parseInt(color);
       else if("color".equalsIgnoreCase(variable))
            this.color = color;
       else
           throw new Exception ("error - property not available"); 
      }
   }

Note, your existing method name 'changeHairColor' doesn't make sense in the context. It should be someething like 'changeProperty' because you are not just changing the 'color', you are changing any available property with this method.

Upvotes: 0

bsiamionau
bsiamionau

Reputation: 8229

The only way to do it in Java is to use Java Reflection API:

public class Test {
    public String name;
    public int age;
    public String hairColor;

    public void setProperty(String property, Object value) {
        try {
            Field declaredField = this.getClass().getDeclaredField(property);
            switch (declaredField.getAnnotatedType().getType().getTypeName()) {
                case "java.lang.String":
                    declaredField.set(this, value);
                    break;
                // handle other types
            }
        } catch (NoSuchFieldException e) {
            // handle exception
        } catch (IllegalAccessException e) {
            // handle exception
        }
    }

    public static void main(String[] args) {
        Test test = new Test();
        test.setProperty("name", "Bob");
        System.out.println(test.name);
    }
}

Upvotes: 3

Related Questions