精华内容
下载资源
问答
  • 在某些场景下我们需要动态生成一些枚举值,主要是通过反射生成,但是这种生成枚举值是不能switch的1.枚举值类public enum CodeInfoEnum {LOCK(1L, 1L, "LOCK_TYPE", "LOCK"), UNLOCK(1L, 2L, "LOCK_TYPE", "LOCK");...

    在某些场景下我们需要动态生成一些枚举值,主要是通过反射生成,但是这种生成枚举值是不能switch的

    1.枚举值类

    public enum CodeInfoEnum {

    LOCK(1L, 1L, "LOCK_TYPE", "LOCK"), UNLOCK(1L, 2L, "LOCK_TYPE", "LOCK");

    public Long classId;

    public Long infoId;

    public String classCode;

    public String infoCode;

    CodeInfoEnum(Long classId, Long infoId, String classCode, String infoCode) {

    this.classId = classId;

    this.infoId = infoId;

    this.classCode = classCode;

    this.infoCode = infoCode;

    }

    public static CodeInfoEnum getByInfoId(Long infoId) {

    return CodeInfoEnum.valueOf(infoId + "");

    }

    public static List getByClassId(Long classId) {

    return Arrays.stream(CodeInfoEnum.values()).filter(item -> item.classId.equals(classId)).collect(Collectors.toList());

    }

    public static CodeInfoEnum getByClassCodeAndInfoCode(String classCode, String infoCode) {

    Optional opt = Arrays.stream(CodeInfoEnum.values()).filter(item -> item.classCode.equals(classCode) && item.infoCode.equals(infoCode)).findFirst();

    return opt.orElse(null);

    }

    @Override

    public String toString() {

    return "CodeInfoEnum{" +

    "classId=" + classId +

    ", infoId=" + infoId +

    ", classCode='" + classCode + '\'' +

    ", infoCode='" + infoCode + '\'' +

    '}';

    }

    }

    2.生成工具类

    public class DynamicEnumTest {

    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));

    }

    /**

    * Add an enum instance to the enum class given as argument

    *

    * @param 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 > void addEnum(Class enumType, String enumName,Class>[] paramClass,Object[] paramValue) {

    // 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 values = new ArrayList(Arrays.asList(previousValues));

    // 3. build new enum

    T newValue = (T) makeEnum(enumType, // The target enum class

    enumName, // THE NEW ENUM INSTANCE TO BE DYNAMICALLY ADDED

    values.size(),

    //new Class>[] {}, // could be used to pass values to the enum constuctor if needed

    paramClass,

    //new Object[] {}

    paramValue

    ); // could be used to pass values to the enum constuctor if needed

    // 4. add new value

    values.add(newValue);

    Object object=values.toArray((T[]) Array.newInstance(enumType, 0));

    // 5. Set new values field

    setFailsafeFieldValue(valuesField, null, object);

    // 6. Clean enum cache

    cleanEnumCache(enumType);

    } catch (Exception e) {

    e.printStackTrace();

    throw new RuntimeException(e.getMessage(), e);

    }

    }

    public static void main(String[] args) {

    //

    synchronized (CodeInfoEnum.class) {

    addEnum(CodeInfoEnum.class, "3", new Class>[]{Long.class, Long.class, String.class, String.class}, new Object[]{2L, 3L, "ActiveStatus", "Active"});

    addEnum(CodeInfoEnum.class, "4", new Class>[]{Long.class, Long.class, String.class, String.class}, new Object[]{2L, 4L, "ActiveStatus", "Inactive"});

    addEnum(CodeInfoEnum.class, "5", new Class>[]{Long.class, Long.class, String.class, String.class}, new Object[]{3L, 5L, "Optype", "OP1"});

    addEnum(CodeInfoEnum.class, "6", new Class>[]{Long.class, Long.class, String.class, String.class}, new Object[]{3L, 6L, "Optype", "OP2"});

    addEnum(CodeInfoEnum.class, "7", new Class>[]{Long.class, Long.class, String.class, String.class}, new Object[]{3L, 7L, "Optype", "OP3"});

    addEnum(CodeInfoEnum.class, "8", new Class>[]{Long.class, Long.class, String.class, String.class}, new Object[]{3L, 8L, "Optype", "OP4"});

    }

    CodeInfoEnum codeInfoEnum =CodeInfoEnum.valueOf("5");

    System.out.println(codeInfoEnum);

    // Run a few tests just to show it works OK.

    System.out.println(Arrays.deepToString(CodeInfoEnum.values()));

    System.out.println("============================打印所有枚举(包括固定的和动态的),可以将数据库中保存的CIC以枚举的形式加载到JVM");

    for(CodeInfoEnum codeInfo:CodeInfoEnum.values()){

    System.out.println(codeInfo.toString());

    }

    System.out.println("============================通过codeId找到的枚举,用于PO转VO的处理");

    CodeInfoEnum activeStatus_Active = CodeInfoEnum.getByInfoId(3L);

    System.out.println(activeStatus_Active);

    System.out.println("============================通过ClassId找到的枚举列表");

    List activeStatusEnumList = CodeInfoEnum.getByClassId(3L);

    for(CodeInfoEnum codeInfo : activeStatusEnumList){

    System.out.println(codeInfo);

    }

    System.out.println("============================通过ClassCode和InfoCode获取枚举,用于导入验证CIC合法性");

    CodeInfoEnum toGetActiveStatus_Active = CodeInfoEnum.getByClassCodeAndInfoCode("ActiveStatus","Active");

    System.out.println(toGetActiveStatus_Active);

    System.out.println("============================通过ClassCode和InfoCode获取枚举,输入不存在的Code,则返回NULL");

    CodeInfoEnum toGetActiveStatus_miss = CodeInfoEnum.getByClassCodeAndInfoCode("ActiveStatus","MISS");

    System.out.println(toGetActiveStatus_miss);

    }

    }

    展开全文
  • ​ merge-plus主要用于字典merge,根据对应的枚举值,merge出枚举值对应的含义。 一、背景 ​ merge-plus目的为了解决前端字典枚举值显示为实际含义的问题,比如H5、app等。在实际项目中,一般都有一个字典的公共...

    ​ merge-plus主要用于字典merge,根据对应的枚举值,merge出枚举值对应的含义。

    一、背景

    ​ merge-plus目的为了解决前端字典枚举值显示为实际含义的问题,比如H5、app等。在实际项目中,一般都有一个字典的公共服务,用于配置字典的相关信息,但在项目开发中,数据库一般存储对应的枚举值,不会存储对应中文含义(中文含义变化,数据库需要同步变化)。前端处理枚举值有2种方案:

    ​ 1、前端开发人员根据后端服务返回的字典码对应的枚举值去字典服务获取相应的中文含义

    ​ 2、后端服务统一处理,把相应的字典码对应的枚举值转化为对应的中文含义返回给前端,前端即可展示

    ​ 为了尽量减少前端工作量,即所有的枚举值中文含义在后端服务统一处理后返回给前端使用,比如在很多前端详情页面,枚举值需要显示为真实的含义,此时即可使用merge-plus解决这一问题。

    二、merge-plus介绍

    ​ merge-plus支持feign直接调用,也支持http方式直接调用,当服务不在同一个注册中心时,feign直连调用也可,但是此时需要指定相应的url,此时指定url直连调用其实和http方式直接调用区别不大,仅仅只是feign主键封装了一层。http直接调用指定相应的url即可。

    ​ merge-plus支持缓存,目前主要是基于redis缓存,当命中缓存时,直接使用缓存数据,未命中缓存,远程获取。项目最初仅仅是为了方便字典而设计,但并不意味着仅仅只能使用于字典,只要响应结果和字典响应结果一致,也可使用,比如,对于一张表,都会记录操作人员,但是数据库中通常都是保存用户编码,此时也可以使用merge获取对应用户编码的中文名等。

    ​ merge-plus使用多线程merge,目的是为解决响应时间问题,提高效率,有更好的用户体验。

    三、merge-plus使用

    1、引入相应jar包

    2021.03.25 升级 1.0.2 新增enabledCache字段,默认是启用缓存,可配置关闭缓存,每次请求获取最新值;fix bug缓存key错误

    2021.03.08 升级 1.0.1

    2020.11.23 发布 1.0.0

    maven

    <dependency>
        <groupId>com.github.carteryh</groupId>
        <artifactId>merge-plus</artifactId>
        <version>1.0.2</version>
    </dependency>
    

    gradle

    compile group: 'com.github.carteryh', name: 'merge-plus', version: '1.0.2'
    

    2、若需要使用redis缓存,特别注意redis序列化

    3、merge方式

    ​ a、feign merge

    ​ feign merge有2种情况,同一个注册中心,url可空。

    ​ @FeignClient(name = “user-center”)

    ​ 当不在同一个注册中心时,需要指定直连url,该方式和http方式类似

    ​ @FeignClient(name = “user-center”, url = “http://localhost:9002”)

    package com.cloud.user;
    
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    import java.util.Map;
    
    // 不在同一个注册中心时,需要指定直连url
    @FeignClient(name = "user-center", url = "http://localhost:9002")
    public interface StaticFeignClient {
     
    	  @GetMapping("/user/dic/merge/{typeCode}")
        Map<String, String> merge(@PathVariable(name = "typeCode", required = true) String typeCode);
    
    }
    

    ​ b、http merge

    ​ http merge主要是为了解决项目中不使用feign而提供的,和feign的直连merge一样。因此必然需要指定远程调用地址。

    package com.cloud.user;
    
    import com.mergeplus.annonation.GetMerge;
    import com.mergeplus.annonation.HttpMerge;
    import org.springframework.web.bind.annotation.PathVariable;
    
    import java.util.Map;
    
    // 需要指定url地址
    @HttpMerge(url = "http://localhost:9002")
    public interface StaticHttpClient {
     
    	  @GetMerge(value = "/user/dic/merge/{typeCode}")
        Map<String, String> merge(@PathVariable(name = "typeCode", required = true) String typeCode);
        
    }
    

    4、远程调用响应数据规范

    ​ 因为支持redis缓存,所以建议使用,提高效率,因为大多数情况下,字典肯定不会经常变更。建议字典缓存使用autoload-cache,autoload-cache相关使用此处不做介绍,相关文档地址:https://github.com/qiujiayu/AutoLoadCache

    字典接口响应规范案例:

        @GetMapping("/dic/merge/{typeCode}")
        @Cache(expire = 3600, key = "#args[0]")
        public Map<String, String> merge(@PathVariable(name = "typeCode", required = true) String typeCode) {
            Map<String, String> map = Maps.newHashMap();
            map.put("a", "A");
            map.put("b","B");
            map.put("c", "C");
            map.put("d","D");
    
            return map;
        }
    

    响应结果规范:

    {
      "a": "A",
      "b": "B",
      "c": "C",
      "d": "D"
    }
    

    5、在需要merge的对象字段上加上相应的注解

    package com.cloud.user;
    
    import com.mergeplus.annonation.MergeField;
    import lombok.Data;
    
    import java.io.Serializable;
    
    @Data
    public class Business implements Serializable {
    
        private static final long serialVersionUID = 1L;
    
        private String value;
    
      	//http merge, cache非必须
        @MergeField(key = "test", sourceKey = "value", client = StaticHttpClient.class, method = "merge", cache = "user-center:test")
        private String valueName;
    
        //feign merge, cache非必须
      	// @FeignClient(name = "user-center", url = "http://localhost:9002")
    		// public interface StaticFeignClient
      	// cache为 user-center:test(应用名拼接冒号,再拼接上key)  cache key: xxx:merge:test
        @MergeField(key = "test", sourceKey = "value", client = StaticFeignClient.class, method = "merge")
        private String valueName2;
    
      	//feign merge, cache非必须  
        @MergeField(key = "test", sourceKey = "value", client = StaticFeignClient.class, method = "merge", cache = "user-center:test")
        private String valueName3;
      
          /**
         * 用户编码  admin
         */
        private String userCode;
    
        /**
         * 用户名称  比如  管理员, enabledCache默认开启缓存,设置为false每次请求获取
         */
        //cache key: xxx:mergeName:admin
        @MergeField(sourceKey = "userCode", client = SysUserFeignClient.class, method = "mergeName", enabledCache = false)
        private String userName;
    
    }
    

    enabledCache默认启用缓存,redis缓存key,当cache为空时

    如果key不为空,实际cache的key为FeignClient的应用名拼接冒号,拼接方法名,拼接冒号,再拼接上注解(@MergeField)中key,比如StaticFeignClient为例:applicationName:method:key,xxx:merge:test。

    key为空,实际cache的key为FeignClient的应用名拼接冒号,拼接方法名,拼接冒号,再拼接value值,比如SysUserFeignClient为例,假设userCode为admin:applicationName:method:value,xxx:mergeName:admin。

    6、merge调用

    ​ 先注入核心merge Bean,然后调用即可,方法支持单个对象merge,也支持List merge。

    	//核心merge Bean注入    
    	@Autowired
      private MergeCore mergeCore;
    
      @Test
      public void test2() throws Exception {
        List<Object> objects = new ArrayList<>();
    
        Business business =  new Business();
        business.setValue("a");
        business.setValue2("0");
        business.setDicValue("d");
        business.setUserCode("A00001");
        business.setRegion("110107");
        objects.add(business);
    
        Business business2 =  new Business();
        business2.setValue("c");
        business2.setValue2("1");
        business2.setDicValue("x");
        business2.setUserCode("U000001");
        business2.setRegion("120103");
        objects.add(business2);
    
        mergeCore.mergeResult(objects);
        System.out.println("=====*******======");
        System.out.println(objects);
      }
    

    7、merge结果

    [Business(value=a, valueName=null, value2=0, valueName2=null, dicValue=d, dicValueNamme=null, userCode=A00001, userName=管理员, region=110107, regionName=石景山区)]
    

    四、详细使用

    ​ 详细使用见demo中spring-cloud-service项目user-center中测试类TestClass。

    五、注意事项

    ​ 使用缓存时,需要注入redis序列化及AutoLoadCache序列化,可参考spring-cloud-service项目中RedisConfiguration及AutoLoadCacheConfig配置。

    六、Demo地址

    demo中有详细使用,有相关测试类等。
    https://github.com/13162576590/merge-plus

    展开全文
  • 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...

    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;

    import sun.reflect.ConstructorAccessor;

    import sun.reflect.FieldAccessor;

    import sun.reflect.ReflectionFactory;

    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));

    }

    /**

    * Add an enum instance to the enum class given as argument

    *

    * @param 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 > void addEnum(Class 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 values = new ArrayList(Arrays.asList(previousValues));

    // 3. build new enum

    T newValue = (T) makeEnum(enumType, enumName, values.size(), additionalTypes, additionalValues);

    // 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);

    }

    }

    }

    测试类

    import java.lang.reflect.Field;

    public class MainTest {

    private static enum TestEnum {

    a(111,"AAA"),

    b(222,"BBB"),

    c(333,"CCC");

    private int value;

    private String text;

    TestEnum(int value,String text){

    this.value = value;

    this.text = text;

    }

    public int getValue() {

    return value;

    }

    public void setValue(int value) {

    this.value = value;

    }

    public String getText() {

    return text;

    }

    public void setText(String text) {

    this.text = text;

    }

    @Override

    public String toString() {

    return "TestEnum{" +

    "value=" + value +

    ", text='" + text + '\'' +

    '}';

    }

    };

    private static void addTestEnum(String enumName,int value,String text){

    DynamicEnumUtil.addEnum(TestEnum.class,enumName,new Class>[] {int.class,String.class},new Object[] {value,text});

    }

    public static void main(String[] args) {

    addTestEnum("d",444,"DDD");

    addTestEnum("e",555,"EEE");

    addTestEnum("f",666,"FFF");

    addTestEnum("g",777,"GGG");

    for (TestEnum testEnum:TestEnum.values()){

    System.out.println(testEnum.toString());

    }

    Class ccc = TestEnum.class;

    Field[] fff = ccc.getDeclaredFields();

    TestEnum testEnum = TestEnum.b;

    switch (testEnum){

    case a:{

    System.out.println("22222reefwsfsds");

    break;

    }

    case b:

    System.out.println("bbb");

    break;

    }

    }

    }

    展开全文
  • 动态修改Java 枚举类的

    千次阅读 2018-09-28 16:56:10
    import java.lang.reflect.AccessibleObject; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util....

    参考地址:111

    package com.itmuch.empty;
    
    import javassist.ClassPool;
    import javassist.CtClass;
    import javassist.CtField;
    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.Method;
    import java.lang.reflect.Modifier;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    
    public class DynamicEnumUtil {
    
        public static void addField(String classname, String[] fields) throws Exception {
            ClassPool pool = ClassPool.getDefault();
            // pool.appendClassPath(new LoaderClassPath(ByteUtil.class.getClassLoader()));
            //		pool.insertClassPath(Thread.currentThread().getContextClassLoader().getResource(".").getFile());
            CtClass cc = pool.get(classname);
            for (String field : fields) {
                field = field.trim().toUpperCase();
                CtField ctf = new CtField(cc, field, cc);
                ctf.setModifiers(Modifier.PUBLIC);
                cc.addField(ctf);
            }
            Class c = cc.toClass();
            addEnum(c, fields, new Class<?>[] {}, new Object[] {});
        }
    
        public static <T> void addEnum(Class enumType, String[] enumNames, Class<?>[] paramClass, Object[] paramValue) {
            // 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();
            Method[] methods = enumType.getDeclaredMethods();
            for (Field field : fields) {
                if (field.getName().contains("$VALUES")) {
                    valuesField = field;
                    break;
                }
            }
            AccessibleObject.setAccessible(new Field[] { valuesField }, true);
            try {
                for (String enumName : enumNames) {
                    enumName = enumName.trim().toUpperCase();
                    // 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, // The target enum class
                            enumName, // THE NEW ENUM INSTANCE TO BE DYNAMICALLY ADDED
                            values.size(),
                            // new Class<?>[] {}, // could be used to pass values to the enum constuctor if needed
                            paramClass,
                            // new Object[] {}
                            paramValue); // could be used to pass values to the enum constuctor if needed
    
                    // 4. add new value
                    values.add(newValue);
                    Object object = values.toArray((T[]) Array.newInstance(enumType, 0));
                    // 5. Set new values field
                    setFailsafeFieldValue(valuesField, null, object);
                    // 6. Clean enum cache
                    cleanEnumCache(enumType);
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e.getMessage(), e);
            }
        }
    
        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));
        }
    
        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 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
        }
    
        public static void main(String[] args) throws Exception {
            addField("com.ctrip.framework.apollo.core.enums.Env", new String[] { "mj1", "mj2" });
    
            Gson gson = new Gson();
            System.out.println(Env.valueOf("MJ1"));
            System.out.println(gson.toJson(Env.values()));
            System.out.println(gson.toJson(Env.valueOf("MJ1")));
            System.out.println(gson.toJson(Env.valueOf("MJ2")));
    
            //        addEnum(Env.class, "testmj", new Class<?>[]{}, new Object[]{});
            //        for(Env codeInfo:Env.values()){
            //            System.out.println(codeInfo.toString());
            //        }
            //        String test="{\"test1\":\"123\",\"test2\":\"456\"}";
            //        Gson gson = new Gson();
            //        Map<String,String> map = gson.fromJson(test, Map.class);
            //        System.out.println(gson.toJson(Env.valueOf("testmj")));
    
        }
    }
    
    
    展开全文
  • 默认情况下 枚举Color 中RED打印的是红色,如果能做到我修改变量colorRed的为黑色时,打印枚举Color 中RED的得到的是黑色(由于项目中大量使用了枚举,所以改项目架构不太现实,另外请考虑如果改,可以在最小的...
  • java5引入了枚举类这...关于枚举类,网上的资料都没怎么提到,如何根据一个动态的输入,来得到该枚举类的实例,这里参考了一篇文章《java switch的使用+switch用String作为条件》public enum Bank {ICBC("95588"...
  • 工作中遇到需要对枚举类的进行动态更新 手动改不现实也不方便 现记录下来方便以后学习使用1.在工程utils包中添加动态更新枚举类得工具类(根据自己得项目,放到指定位置调用就可以)2.一开始陷入了误区,认为要根据...
  • 动态增加枚举值

    2020-05-12 10:17:44
        之前做东西遇到了这么一个需求,希望动态的增加枚举类中的枚举值。我们正常情况下都是先定义枚举类,然后写好静态的枚举值,然后在代码中使用,那可不可以动态的增加枚举呢?研究后通过反射是可以实现的。...
  • java枚举的集中管理

    2020-07-28 16:36:28
    java枚举的集中管理 一、 产品中遇到的实际情况枚举类泛滥 这个 这个 这个 这个 在 JDK 1.5 之前没有枚举类型,那时候一般用接口常量来替代。而使用 Java 枚举类型 enum 可以更贴近地表示这种常量。但是在项目中...
  • java枚举

    2015-07-02 01:25:02
    java5引入了枚举类这一新特性...关于枚举类,网上的资料都没怎么提到,如何根据一个动态的输入,来得到该枚举类的实例,这里参考了一篇文章《java switch的使用+switch用String作为条件》 [java] v
  • java动态更新枚举

    2019-10-04 07:41:26
    工作中遇到需要对枚举类的进行动态更新 手动改不现实也不方便 现记录下来方便以后学习使用 1.在工程utils包中添加动态更新枚举类得工具类(根据自己得项目,放到指定位置调用就可以) 2.一开始陷入了误区,认为要...
  • java枚举的概念与应用

    2016-02-13 19:33:07
    Java SE 5中引入了全新的枚举(Enum)概念,个人认为十分有用,整理一些相关概念和基本用法。  1.1:枚举的概念  枚举,即枚举类,准确的说枚举即是一个类。使用关键字enum+类名声明一个枚举类,然后将一组...
  • 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.A...
  • 调用一个service功能,需要传递枚举,如果传递其他的还需要修改底层的代码。于是就想到用动态的方式添加枚举。参考了其他人写的例子,自己尝试了一下,说不定之后可以用到,所以在这里纪录一下。 枚举: @Getter ...
  • java5引入了枚举类这...关于枚举类,网上的资料都没怎么提到,如何根据一个动态的输入,来得到该枚举类的实例,这里参考了一篇文章《java switch的使用+switch用String作为条件》     public enum Bank { ...
  • 这种动态获取的信息已经动态调用对象的方法的功能称为java语言的反射机制。 2. java获取Class对象的三种方式 Class.forName(“类路径”); 调用属性,通过.class来获取其对应的Class对象;...
  • 在项目开发中好多地方用了枚举,要把枚举显示到下拉列表框中我们平常的方法就是在下拉列表控件中一个一个添在项目开发...这里我有反射动态的绑定枚举值就可以很方便的做修改了,代码如下:public enum Eume{星期一,...
  • 枚举枚举是一种特殊的类,其中的每个元素都是该类的一个实例对象 枚举可以让编译器在编译时就可以控制源程序中填写的非法 枚举就相当于一个类,其中也可以定义构造方法、成员变量、普通方法和抽象方法 枚举...
  • Java--002动态--注解

    2019-10-17 00:03:54
    1. Java元注解 目的:创建注解的时候...可选的属性都是ElementType的一个枚举 TYPE:表示类、接口(包括注解),或者枚举说明 FIFLD:字段,包括枚举常量 METHOD:方法 PARAMETER:方法中的参数 CONSTRUCTOR:构...
  • Java注解的部分实现:动态代理

    千次阅读 2016-04-11 18:18:03
    之前一直有一个疑问:在我们获取方法、属性、类、包等等(java.lang.annotation.ElementType枚举类里面的代都可以)的注解之后,就可以直接通过注解的方法来获取其对应的属性,但是我们知道注解是一个特殊的接口,...

空空如也

空空如也

1 2 3 4 5 6
收藏数 114
精华内容 45
关键字:

java枚举动态值

java 订阅