java enum class dynamic update

Meet the need for enumeration class values ​​manually updated dynamically change the unrealistic work is not easy now easy to learn to use to record later

1. Add the dynamic update enumeration class have tools in engineering utils package (according to their own projects too, can call into the specified location)

2. began to fall into a misunderstanding that you want to modify based on my own was enumerated classes, addEnum and makeEnum method because the online examples are two parameters available,

And I was five, and get a long time (by their own stupid halo) realize that it is an array ah.

package com.genju.ziji.dexiangmu.util;

import sun.reflect.ConstructorAccessor;
import sun.reflect.FieldAccessor;
import sun.reflect.ReflectionFactory;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/ **
* Dynamic new enumeration tools
* /
public class DynamicEnumUtil {
Private static ReflectionFactory reflectionFactory ReflectionFactory.getReflectionFactory = ();

private static void setFailsafeFieldValue(Field field, Object target, Object value) throws NoSuchFieldException,
IllegalAccessException {

// let's make the field accessible
field.setAccessible(true);

// next we change the modifier in the Field instance to
// not be final anymore, thus tricking reflection into
// letting us modify the static final field
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
int modifiers = modifiersField.getInt(field);

// blank out the final bit in the modifiers int
modifiers &= ~Modifier.FINAL;
modifiersField.setInt(field, modifiers);

FieldAccessor fa = reflectionFactory.newFieldAccessor(field, false);
fa.set(target, value);
}

private static void blankField(Class<?> enumClass, String fieldName) throws NoSuchFieldException,
IllegalAccessException {
for (Field field : Class.class.getDeclaredFields()) {
if (field.getName().contains(fieldName)) {
AccessibleObject.setAccessible(new Field[]{field}, true);
setFailsafeFieldValue(field, enumClass, null);
break;
}
}
}

private static void cleanEnumCache(Class<?> enumClass) throws NoSuchFieldException, IllegalAccessException {
blankField(enumClass, "enumConstantDirectory"); // Sun (Oracle?!?) JDK 1.5/6
blankField(enumClass, "enumConstants"); // IBM JDK
}

private static ConstructorAccessor getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes)
throws NoSuchMethodException {
Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2];
parameterTypes[0] = String.class;
parameterTypes[1] = int.class;
System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
return reflectionFactory.newConstructorAccessor(enumClass.getDeclaredConstructor(parameterTypes));
}

private static Object makeEnum(Class<?> enumClass, String value, int ordinal, Class<?>[] additionalTypes,
Object[] additionalValues) throws Exception {
Object[] parms = new Object[additionalValues.length + 2];
parms[0] = value;
parms[1] = Integer.valueOf(ordinal);
System.arraycopy(additionalValues, 0, parms, 2, additionalValues.length);
return enumClass.cast(getConstructorAccessor(enumClass, additionalTypes).newInstance(parms));
}

/**
* 判断枚举是否已存在
*
* @param values
* @param enumName
* @param <T>
* @return
*/
public static <T extends Enum<?>> boolean contains(List<T> values, String enumName) {
for (T value : values) {
if (value.name().equals(enumName)) {
return true;
}
}
return false;
}


/**
* Add an enum instance to the enum class given as argument
*
* @param <T> the type of the enum (implicit)
* @param enumType the class of the enum to be modified
* @param enumName the name of the new enum instance to be added to the class.
*/
@SuppressWarnings("unchecked")
public static <T extends Enum<?>> void addEnum(Class<T> enumType, String enumName, Class<?>[] additionalTypes, Object[] additionalValues) {

// 0. Sanity checks
if (!Enum.class.isAssignableFrom(enumType)) {
throw new RuntimeException("class " + enumType + " is not an instance of Enum");
}

// 1. Lookup "$VALUES" holder in enum class and get previous enum instances
Field valuesField = null;
Field[] fields = enumType.getDeclaredFields();
for (Field field : fields) {
if (field.getName().contains("$VALUES")) {
valuesField = field;
break;
}
}
AccessibleObject.setAccessible(new Field[]{valuesField}, true);

try {

// 2. Copy it
T[] previousValues = (T[]) valuesField.get(enumType);
List<T> values = new ArrayList<T>(Arrays.asList(previousValues));

// 3. build new enum
T newValue = (T) makeEnum(enumType, enumName, values.size(), additionalTypes, additionalValues);

if (contains(values, enumName)) {
System.out.println("Enum:" + enumName + " 已存在");
return;
}

// 4. add new value
values.add(newValue);

// 5. Set new values field
setFailsafeFieldValue(valuesField, null, values.toArray((T[]) Array.newInstance(enumType, 0)));

// 6. Clean enum cache
cleanEnumCache(enumType);

} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e.getMessage(), e);
}
}

}

3. Test

public static void main(String args[]) {

  addEnum("1","2","3","4","5");

  for(SubBank e : SunBank.values()){

    System.out.println(e.getBankName());

  }

}

private static void addEnum(String enumName,String id,String name,String desc,AreaType       areaType,List<Class<? extends Enum>> paramTypes){

      DynamicEnumUtil.addEnum(Subank.class,enumName,

      new Class<?>[]{Stirng.class,String.class,AreaType.class,List.Class}, 

      new object[]{id,nae,desc,areaType,paramTypes});

  }

 

Finally, look at the effect of printing is ok enough to add on, I will enumerate here is to write directly on the class, there is a need can also be made dynamically according to their needs too;

If the place was not exactly welcome the guidance

Guess you like

Origin www.cnblogs.com/KpGo/p/11527473.html