0

I have a class with a mix of booleans and integers:

class Soup {
    boolean mItem1 = false
    boolean mItem2 = false
    int     mItem3 = 10
    boolean mItem4 = false
    int     mItem5 = 100 
{

I also have a method "void addIngredient(String itemName)" that I will pass a string value like "Item1" or "Item4".

void addIngredient(String itemName) {
    // I need help with the following line
    Soup.m(itemName) = true
}

How can I set the value of variable Soup.mItem1 for example, WITHOUT using an if statement or switch. For example I might add up to 25 or 50 "mItems" variables that may either be a boolean or integer value.

I basically want to take Soup.m and concatenate the string I pass (Item1 for example) to make the string "Soup.mItem1" and then set a value, such has "Soup.mItem1 = true" or "Soup.nItem3 = 1000".

Selzier
  • 101
  • 1
  • 6
  • 19
  • Please clarify your question a bit more. What is `Soup.m(...)`? And what do you mean when you say - *25 or 50 "Items" that could be either a Int or Bool*? – Rohit Jain Oct 15 '13 at 03:34
  • Ok. You can't do this in Java. What you want is an `ArrayList` or a `HashMap` to store various values. Maintain an `ArrayList`, and an `ArrayList`, and add values to it. – Rohit Jain Oct 15 '13 at 03:44
  • void addIngredient(String itemName) throws Exception { Soup.class.getDeclaredField("m" + itemName).setBoolean(this, false); } – Selzier Oct 15 '13 at 03:55
  • Can I do something like that? ^ – Selzier Oct 15 '13 at 03:55

3 Answers3

0

Take a look at this other post that talk about how to turn a string that is passed in as a parameter or a variable and assign it a field. I think this will work, but I'd still do some more research: Creating a variable name using a String value and Get variable by name from a String

This is what I came up with:

final Map<String, boolean> itemType = new HashMap<>();

void addIngredient(String itemName) {
itemName="m" + itemName;
itemType.put(itemName, true);
}

Think this should work.

Community
  • 1
  • 1
Wold
  • 952
  • 1
  • 13
  • 25
0

You want to use reflection.

import java.lang.reflect.Field;

public class Main 
{
    private boolean mItem1;
    private int mItem2;

    public static void main(String[] args)
        throws NoSuchFieldException, 
               IllegalArgumentException, 
               IllegalAccessException 
    {
        final Main instance;

        instance = new Main();
        instance.addIngredient("Item1");
        instance.setIngredientAmount("Item2", 1000);

        System.out.println(instance.mItem1);
        System.out.println(instance.mItem2);
    }

    public void addIngredient(final String itemName) 
        throws NoSuchFieldException, 
               IllegalArgumentException, 
               IllegalAccessException
    {
        final Class<Main> clazz;
        final Field       item;

        clazz = Main.class;
        item  = clazz.getDeclaredField("m" + itemName);
        item.set(this, true);
    }

    public void setIngredientAmount(final String itemName,
                                    final int    value)
        throws NoSuchFieldException, 
               IllegalArgumentException, 
               IllegalAccessException
    {
        final Class<Main> clazz;
        final Field       item;

        clazz = Main.class;
        item  = clazz.getDeclaredField("m" + itemName);
        item.set(this, value);
    }
}

I would not actually recommend this, but it should satisfy your requirements.

TofuBeer
  • 60,850
  • 18
  • 118
  • 163
0

You can do it with Reflection, but Reflection has a lot of caveats, including performance and a very tight coupling of code. So, I would recommend not using Reflection, but if you must, you can do it like this.

OriginalClass

public class OriginalClass {
    public int var1;
    public String var2;
    public boolean var3;
}

Main

import java.lang.reflect.Field;
public class Main {
    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        OriginalClass orig = new OriginalClass();
        orig.var1 = 1;
        orig.var2 = "Hello";
        orig.var3 = true;
        for(int i = 0; i <= 3; i++) {
            Field origVar = OriginalClass.class.getDeclaredField("var" + i);
            System.out.println(origVar.get(orig));
        }
    }
}

Alternatively, you can use getFields and then loop over all the fields.

for(Field origVar : orig.getFields())
    System.out.println(origVar.get(orig));

Similar to the get() method, there is the set() method on Field. The signature is

void set(Object obj, Object value);

Note : Normally, due to encapsulation, your member variables will be hidden, so you must access them through their getters and setters, something like this.

Method m = OriginalClass.class.getDeclaredMethod("getVar1", null);
System.out.println(m.invoke(orig));
m = OriginalClass.class.getDeclaredMethod("setVar1", Integer.TYPE);
m.invoke(orig, 3);
System.out.println(orig.var1); //Will print 3
Achrome
  • 7,773
  • 14
  • 36
  • 45