import java.lang.reflect.Field; | |
import java.lang.reflect.Method; import java.lang.reflect.Constructor; | |
/** | |
* Java doesn't allow creation of enum dynamically through reflection. It will | |
* throw "Cannot reflectively create enum objects". | |
* | |
* This code will creates enum by skipping the exception. | |
* | |
* Note: Tested this code Oracle JDK | |
* | |
* | |
* @note Use this when you need to return a default value for a specified enum, | |
* which is not in your ENUM list. If your enum is auto generated and | |
* cannot modify or use a defined value as default, you can use | |
* EnumCreator. | |
* | |
*/ | |
public class EnumCreator { | |
public static <T extends Enum<?>> T createEnum(String enumString, | |
Class<T> enumType, Object... params) { | |
if (!Enum.class.isAssignableFrom(enumType)) { | |
throw new RuntimeException("class " + enumType | |
+ " is not an instance of Enum"); | |
} | |
T constructObj = null; | |
try { | |
Constructor<?> con = enumType.getDeclaredConstructors()[0]; | |
Method[] methods = con.getClass().getDeclaredMethods(); | |
for (Method m : methods) { | |
if (m.getName().equals("acquireConstructorAccessor")) { | |
m.setAccessible(true); | |
m.invoke(con, new Object[0]); | |
} | |
} | |
Field[] fields = con.getClass().getDeclaredFields(); | |
Object ca = null; | |
for (Field f : fields) { | |
if (f.getName().equals("constructorAccessor")) { | |
f.setAccessible(true); | |
ca = f.get(con); | |
} | |
} | |
if (ca != null) { | |
Object[] enums = Object[].class.cast(enumType.getMethod( | |
"values").invoke(null)); | |
Method m = ca.getClass().getMethod("newInstance", | |
new Class[] { Object[].class }); | |
m.setAccessible(true); | |
Object[] args = new Object[2 + params.length]; | |
args[0] = enumString; // name | |
args[1] = enums.length; // Ordinal | |
int argslen = 2; | |
for (Object param : params) { | |
args[argslen++] = param; | |
} | |
constructObj = enumType.cast(m | |
.invoke(ca, new Object[] { args })); | |
} | |
} catch (Throwable e) { | |
e.printStackTrace(); | |
} | |
return constructObj; | |
} | |
} |