Re: Setting class variables dynamically from a config file
Joel Gilmore wrote:
Hi all,
I'm writing a java program (an evolution simulator) that has a large
number (>50) of preferences that can be tweaked (e.g., foodAvailable,
mutationRate, etc). They are booleans, ints and doubles. At present,
these are variables in a class, and I'm trying to work out the best
way for the user to be able to set these variables. Some of the most
important ones I've put into a preference box, but for the others that
will only get changed rarely, I'm trying to find a more sustainable
solution.
I envision having a user-editable config file which would be loaded at
the start, either in XML format or simply
foodAvailable = 20
mutationRate = 0.01
I know I could code a massive if-then-else block to handle all the
different variables (if (key="foodAvailable") foodAvailable=value;),
but I would have to update that every time I add a new variable as the
program grows (prone to error, and just looks like bad code). Is there
a way that I could dynamically read in the variable name and attempt
to set it? It would also be very convenient to be able to do the
reverse and dynamically generate the config file from my class
(getting its variable names and their values).
I've heard about Reflection, but not certain if that's where I should
start. Another option would be to store the parameters not as
variables but in some sort of dictionary with String keys. However,
speed is an issue and I'm worried if I have to do a dictionary lookup
for every variable in my code it's going to slow things down
significantly (is that fear unfounded?). I could read them out of the
dictionary into the class variables, but that would again require hard
coding the variable names?
Two approaches come to mind:
1. Use Spring or another similar project to handle the configuration
step - this will also enable some cool stuff for assembling objects at
startup. The downside is that the configuration format will be one
designed for some really general-purpose tasks: using Spring, you'd
get something like:
....
<bean id="core" class="com.example.SimulationCore">
<property name="foodAvailable">
<value>20</value>
</property>
</bean>
....
which might be a little verbose. There are other context
configurators available for it if you do a little digging, though.
2. There is a class in Commons Beanutils which adapts arbitrary
beans to the Map API, allowing you to access its properties by name.
You can do the same thing using the java Beans (java.beans) API
yourself, too. You can iterate through a java.util.Properties object
(easily loaded from a file of the format
key = value
) and apply each entry to a bean.
Both of these approaches rely on your code following the bean
conventions for property access: int getFoo()/void setFoo (int) for a
property named 'foo' of type int.
-o