zoukankan      html  css  js  c++  java
  • JAVA动态添加枚举值

      1 import java.lang.reflect.AccessibleObject;
      2 import java.lang.reflect.Array;
      3 import java.lang.reflect.Field;
      4 import java.lang.reflect.Modifier;
      5 import java.util.ArrayList;
      6 import java.util.Arrays;
      7 import java.util.List;
      8 
      9 import sun.reflect.ConstructorAccessor;
     10 import sun.reflect.FieldAccessor;
     11 import sun.reflect.ReflectionFactory;
     12 
     13 /**
     14  * @Description: 动态枚举操作工具
     15  * @author wly
     16  * @date 2019年11月29日
     17  */
     18 @SuppressWarnings("restriction")
     19 public class DynamicEnumUtils {
     20     private static ReflectionFactory reflectionFactory = ReflectionFactory.getReflectionFactory();
     21 
     22     private static void setFailsafeFieldValue(Field field, Object target, Object value)
     23         throws NoSuchFieldException, IllegalAccessException {
     24 
     25         field.setAccessible(true);
     26 
     27         Field modifiersField = Field.class.getDeclaredField("modifiers");
     28         modifiersField.setAccessible(true);
     29         int modifiers = modifiersField.getInt(field);
     30 
     31         modifiers &= ~Modifier.FINAL;
     32         modifiersField.setInt(field, modifiers);
     33 
     34         FieldAccessor fa = reflectionFactory.newFieldAccessor(field, false);
     35         fa.set(target, value);
     36     }
     37 
     38     private static void blankField(Class<?> enumClass, String fieldName)
     39         throws NoSuchFieldException, IllegalAccessException {
     40         for (Field field : Class.class.getDeclaredFields()) {
     41             if (field.getName().contains(fieldName)) {
     42                 AccessibleObject.setAccessible(new Field[] {field}, true);
     43                 setFailsafeFieldValue(field, enumClass, null);
     44                 break;
     45             }
     46         }
     47     }
     48 
     49     private static void cleanEnumCache(Class<?> enumClass) throws NoSuchFieldException, IllegalAccessException {
     50         blankField(enumClass, "enumConstantDirectory"); // Sun (Oracle?!?) JDK 1.5/6
     51         blankField(enumClass, "enumConstants"); // IBM JDK
     52     }
     53 
     54     private static ConstructorAccessor getConstructorAccessor(Class<?> enumClass, Class<?>[] additionalParameterTypes)
     55         throws NoSuchMethodException {
     56         Class<?>[] parameterTypes = new Class[additionalParameterTypes.length + 2];
     57         parameterTypes[0] = String.class;
     58         parameterTypes[1] = int.class;
     59         System.arraycopy(additionalParameterTypes, 0, parameterTypes, 2, additionalParameterTypes.length);
     60         return reflectionFactory.newConstructorAccessor(enumClass.getDeclaredConstructor(parameterTypes));
     61     }
     62 
     63     private static Object makeEnum(Class<?> enumClass, String value, int ordinal, Class<?>[] additionalTypes,
     64         Object[] additionalValues) throws Exception {
     65         Object[] parms = new Object[additionalValues.length + 2];
     66         parms[0] = value;
     67         parms[1] = Integer.valueOf(ordinal);
     68         System.arraycopy(additionalValues, 0, parms, 2, additionalValues.length);
     69         return enumClass.cast(getConstructorAccessor(enumClass, additionalTypes).newInstance(parms));
     70     }
     71 
     72     @SuppressWarnings("unchecked")
     73     public static <T extends Enum<?>> void addEnum(Class<T> enumType, String enumName, Class<?>[] additionalTypes,
     74         Object[] additionalValues) {
     75 
     76         // 判断该枚举类是否继承自枚举Enum
     77         if (!Enum.class.isAssignableFrom(enumType)) {
     78             throw new RuntimeException("class " + enumType + " is not an instance of Enum");
     79         }
     80 
     81         // 1. Lookup "$VALUES" holder in enum class and get previous enum instances
     82         Field valuesField = null;
     83         Field[] fields = enumType.getDeclaredFields();
     84         for (Field field : fields) {
     85             if (field.getName().contains("$VALUES")) {
     86                 valuesField = field;
     87                 break;
     88             }
     89         }
     90         AccessibleObject.setAccessible(new Field[] {valuesField}, true);
     91 
     92         try {
     93 
     94             // 2. Copy it
     95             T[] previousValues = (T[])valuesField.get(enumType);
     96             List<T> values = new ArrayList<T>(Arrays.asList(previousValues));
     97 
     98             // 3. build new enum
     99             T newValue = (T)makeEnum(enumType, enumName, values.size(), additionalTypes, additionalValues);
    100 
    101             // 4. add new value
    102             values.add(newValue);
    103 
    104             // 5. Set new values field
    105             setFailsafeFieldValue(valuesField, null, values.toArray((T[])Array.newInstance(enumType, 0)));
    106 
    107             // 6. Clean enum cache
    108             cleanEnumCache(enumType);
    109 
    110         } catch (Exception e) {
    111             throw new RuntimeException(e.getMessage(), e);
    112         }
    113     }
    114 }
  • 相关阅读:
    django的信号
    网络安全
    网络干货,无论是运维还是开发都要知道的网络知识系列之(九)
    一些职场的忠告
    自动化测试如何解决验证码的问题
    通过python切换hosts文件
    【转】web常见安全问题以及测试方法
    【转】做好软件测试需要具备的思维方式
    【转】创业泡沫的「军功章」,高薪低能的程序员要分走一半
    【转】黑盒测试中的一些小经验分享
  • 原文地址:https://www.cnblogs.com/wly1-6/p/14448910.html
Copyright © 2011-2022 走看看