From your own answer, I read that you want to use enum entries as keys and default values for the actual configuration that is stored in the map in the class OMG
. This configuration should also be written to a file.
Now, you have to make a design decision: When do you want to be able to change which configuration keys can be used and/or the default values? While the program is already running (at run-time) or when the program is recompiled (at compile-time)?
Your description suggests that you want to be able to change them at run-time. Is this correct? Also, is this really needed? Your existing code will probably not use values which are provided for the new keys. Also, a changed default value will probably not have an effect, since the value was already initialized using the old default value.
If you really want to change these information at run-time, then you should not use an enum to store and load them. While this style of programming might work in scripting languages like JavaScript, it does not work well in Java. An enum, like any other code is not supposed to be changed at run-time, but it should be given at compile-time.
Since in Java the code is not supposed to be changed at run-time, the JVM does not even allow to simply reload a class, without doing some class loader magic. You normally want to avoid this whenever possible. For more information about this, see here. It is not impossible to reload a class at run-time, but it is definitely the wrong solution to the problem that you are facing.
So, what is a correct solution? I am still not convinced that you really need to change the information at run-time. If this is correct and you only need to change the information at compile-time, you can simply use your current enum approach. However, you can simplify it to not load the class by name, please see below for more details about a possible implementation.
If you really need to be able to change the information at run-time, you should not store the information in the code, but in a file. This enables you to easily reload the information by re-reading the file. You can use a properties file, which is common in the Java world, see here. If you need a more structured file format, you can use a JSON file. In Java, you can use Gson to work with JSON files, see here.
This works for me:
package test;
import java.util.Arrays;
import java.util.EnumMap;
public class Test {
public static enum SETTINGS {
Setting1("OMG setting 1"), Setting2("OMG setting 2");
private String key;
@Override
public String toString() {
return "SETTINGS: " + key;
}
SETTINGS(String key) {
this.key = key;
}
}
public static class OMG<E extends Enum<E>> {
String name;
EnumMap<E, String> settings;
public OMG(String name, EnumMap<E, String> settings) {
this.name = name;
this.settings = settings;
}
public static <E extends Enum<E>> OMG<E> create(String name,
Class<E> enumClass) {
return new OMG<E>(name, new EnumMap<E, String>(enumClass));
}
}
public static void main(String[] args) {
try {
Class c = Class.forName("test.Test$SETTINGS");
// alternatively you can use:
// Class<SETTINGS> c = SETTINGS.class;
System.out.println(Arrays.toString(c.getEnumConstants()));
OMG.create("foobar", c);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
I assumed that you want to pass any enum type to the class OMG
and not only SETTINGS
. If it should only be SETTINGS
, you might as well just use SETTINGS
directly in your code. This is why I moved the SETTINGS
enum out of the OMG
class.
Next, I added a generic type parameter E
to the class OMG
, so OMG
does not directly depend on SETTINGS
. To enable easier initialization, I added a static factory method to OMG
, which also uses a generic type parameter E
. It only receives the name and the class objects which matches E
. You need the class objects, since in Java you cannot directly use the generic type parameters for reflection.
Also, I replaced the HashMap
by an EnumMap
, since EnumMap
is an optimized map implementation when the key is an enum.
Finally, the initialization of the OMG
class: If you really need to create the class object from the name of the class, using reflection, you can use the code as is. Note that this will produce a warning. However, most of the time you want to use the class objects directly, like in the commented line of code. If you use this second method, you will not get a warning and you can also omit the try-catch block.