修改Enum

修改Enum,简单又快捷

枚举类

public enum Color {
	RED, GREEN, BLUE;
}

测试方法

/**
 * @author zzs
 */
@RestController
@Slf4j
@RequestMapping("/test")
@Api(tags = "测试")
public class TestController {

	static void makeAccessible(Field field) throws Exception {
		field.setAccessible(true);
		Field modifiersField = Field.class.getDeclaredField("modifiers");
		modifiersField.setAccessible(true);
		modifiersField.setInt(field, field.getModifiers() & ~ Modifier.FINAL);
	}


	protected static Field getEnumsArrayField(Class< ? > ec) throws Exception {
		Field field = ec.getDeclaredField("$VALUES");
		field.setAccessible(true);
		return field;
	}

	protected static void clearFieldAccessors(Field field) throws ReflectiveOperationException {
		Field fa = Field.class.getDeclaredField("fieldAccessor");
		fa.setAccessible(true);
		fa.set(field, null);

		Field ofa = Field.class.getDeclaredField("overrideFieldAccessor");
		ofa.setAccessible(true);
		ofa.set(field, null);

		Field rf = Field.class.getDeclaredField("root");
		rf.setAccessible(true);
		Field root = (Field) rf.get(field);
		if (root != null) {
			clearFieldAccessors(root);
		}
	}

	protected static <E extends Enum<E>> void setEnumsArray(Class<E> ec, E... e) throws Exception {
		Field field = ec.getDeclaredField("$VALUES");
		Field modifiersField = Field.class.getDeclaredField("modifiers");
		field.setAccessible(true);
		modifiersField.setAccessible(true);
		modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
		field.set(ec, e);
	}

	public static void main2(String[] args) {
		Field[] declaredFields = Color.class.getDeclaredFields();
		for (Field field : declaredFields) {
			if (Modifier.isStatic(field.getModifiers())) {
				System.out.println(field.getName() +":" + field.getType());
			}
		}
	}

	public static void main1(String[] args) throws Exception{



		Color[] values = Color.values();
		System.out.println(Arrays.toString(values));
		System.out.println(Arrays.toString((Object[]) getEnumsArrayField(Color.class).get(null)));
		clearFieldAccessors(getEnumsArrayField(Color.class));
		setEnumsArray(Color.class, Color.BLUE, Color.GREEN, Color.RED, Color.BLUE);
		System.out.println(Arrays.toString(Color.values()));
	}




	public static void main(String[] args)   {


		try {
			Color[] values = Color.values();
			System.out.println(Arrays.toString(values));

			Class<Color> enumClass = Color.class;
           // 找到构造函数,并使其可访问
			Constructor< ? > constructor = enumClass.getDeclaredConstructors()[0];
			constructor.setAccessible(true);

          // 跳过枚举检查
			Field constructorAccessorField = Constructor.class.getDeclaredField("constructorAccessor");
			constructorAccessorField.setAccessible(true);
          // sun.reflect.ConstructorAccessor -> 我们不应该使用它,如果你需要使用它,最好不要导入它,只能通过反射来使用。(包可能会改变,在Java 9中也会)
			ConstructorAccessor ca = (ConstructorAccessor) constructorAccessorField.get(constructor);
			if (ca == null) {
				Method acquireConstructorAccessorMethod = Constructor.class.getDeclaredMethod("acquireConstructorAccessor");
				acquireConstructorAccessorMethod.setAccessible(true);
				ca = (ConstructorAccessor) acquireConstructorAccessorMethod.invoke(constructor);
			}
         // 注意,构造函数包含两个附加参数,名称和序号.你也可以调用它使用反射
			Color enumValue = (Color) ca.newInstance(new Object[]{"WHITE", 1});

			Field valuesField = Color.class.getDeclaredField("$VALUES");
			makeAccessible(valuesField);
           //复制旧值到新数组并添加我们的新字段。
			Color[] oldValues = (Color[]) valuesField.get(null);
//			Color[] newValues = new Color[oldValues.length + 1];
//			System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
//			newValues[oldValues.length] = enumValue;

			Color[] newValues = new Color[oldValues.length];
			System.arraycopy(oldValues, 0, newValues, 0, oldValues.length);
			newValues[1] = enumValue;
			valuesField.set(null, newValues);


			Field enumConstantDirectoryField = Class.class.getDeclaredField("enumConstantDirectory");
			enumConstantDirectoryField.setAccessible(true);
			enumConstantDirectoryField.set(Color.class, null);
			Field enumConstantsField = Class.class.getDeclaredField("enumConstants");
			enumConstantsField.setAccessible(true);
			enumConstantsField.set(Color.class, null);

			Color[] values2 = Color.values();

			System.out.println(Arrays.toString(values2));

			System.out.println("-----------------------------------");

//			Color[] values3 = Color.values();
//			System.out.println(Arrays.toString(values3));
//			Field enumConstantDirectoryField = Class.class.getDeclaredField("enumConstantDirectory");
//			enumConstantDirectoryField.setAccessible(true);
//			enumConstantDirectoryField.set(Color.class, null);
//			Field enumConstantsField = Class.class.getDeclaredField("enumConstants");
//			enumConstantsField.setAccessible(true);
//			enumConstantsField.set(Color.class, null);
//			Color[] values4 = Color.values();
//
//			System.out.println(Arrays.toString(values4));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

启动main方法发现枚举类被改变。原理可知通过巧妙的方法绕过了枚举检查

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值