Color
javap -c
static {};
Code:
0: new #1 // class playground/Color
3: dup
4: ldc #14 // String RED
6: iconst_0
7: invokespecial #15 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #19 // Field RED:Lplayground/Color;
13: new #1 // class playground/Color
16: dup
17: ldc #21 // String GREEN
19: iconst_1
20: invokespecial #15 // Method "<init>":(Ljava/lang/String;I)V
23: putstatic #22 // Field GREEN:Lplayground/Color;
26: new #1 // class playground/Color
29: dup
30: ldc #24 // String BLUE
32: iconst_2
33: invokespecial #15 // Method "<init>":(Ljava/lang/String;I)V
36: putstatic #25 // Field BLUE:Lplayground/Color;
39: iconst_3
40: anewarray #1 // class playground/Color
43: dup
44: iconst_0
45: getstatic #19 // Field RED:Lplayground/Color;
48: aastore
49: dup
50: iconst_1
51: getstatic #22 // Field GREEN:Lplayground/Color;
54: aastore
55: dup
56: iconst_2
57: getstatic #25 // Field BLUE:Lplayground/Color;
60: aastore
61: putstatic #27 // Field ENUM$VALUES:[Lplayground/Color;
64: return
ENUM$VALUES
Field[] declaredFields = Color.class.getDeclaredFields();
for (Field field : declaredFields) {
if (Modifier.isStatic(field.getModifiers())) {
System.out.println(field.getName() + ": " + field.getType());
}
}
RED: class playground.ReflectEnum$Color
GREEN: class playground.ReflectEnum$Color
BLUE: class playground.ReflectEnum$Color
ENUM$VALUES: class [Lplayground.ReflectEnum$Color;
protected static <E extends Enum<E>> E[] getEnumsArray(Class<E> ec) throws Exception {
Field field = ec.getDeclaredField("ENUM$VALUES");
field.setAccessible(true);
return (E[]) field.get(ec);
}
Color[] colors = getEnumsArray(Color.class);
colors[0] = Color.GREEN;
colors[1] = Color.RED;
colors[2] = Color.BLUE;
for (Color color : Color.values()) {
System.out.println(action + ":" + color.ordinal());
}
GREEN:1
RED:0
BLUE:2
null
Color[] colors = getEnumsArray(Color.class);
colors[0] = Color.GREEN;
colors[1] = Color.RED;
colors[2] = null;
GREEN:1
RED:0
Exception in thread "main" java.lang.NullPointerException
at playground.ReflectEnum.main(ReflectEnum.java:57)
System.out.println(Color.valueOf("GREEN"));
System.out.println(Color.valueOf("RED"));
System.out.println(Color.valueOf("BLUE"));
Exception in thread "main" java.lang.NullPointerException
at java.lang.Class.enumConstantDirectory(Class.java:3236)
at java.lang.Enum.valueOf(Enum.java:232)
at playground.Color.valueOf(Color.java:1)
at playground.ReflectEnum.main(ReflectEnum.java:48)
ReflectEnum.java:48
Color.valueOf("GREEN")
valueOf
Enum.valueOf(Color.class, "BLUE")
Color.BLUE
static final
Change private static final field using Java reflection
protected static <E extends Enum<E>> void setEnumsArray(Class<E> ec, E... e) throws Exception {
Field field = ec.getDeclaredField("ENUM$VALUES");
Field modifiersField = Field.class.getDeclaredField("modifiers");
field.setAccessible(true);
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(ec, e);
}
setEnumsArray(Color.class, Color.BLUE, Color.GREEN, Color.RED, Color.BLUE)
Exception in thread "main" java.lang.IllegalAccessException: Can not set static final [Lplayground.Color; field playground.Color.ENUM$VALUES to [Lplayground.Color;
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:80)
at sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl.set(UnsafeQualifiedStaticObjectFieldAccessorImpl.java:77)
at java.lang.reflect.Field.set(Field.java:758)
at playground.ReflectEnum.setEnumsArray(ReflectEnum.java:76)
at playground.ReflectEnum.main(ReflectEnum.java:37)
Radiodef
protected static Field getEnumsArrayField(Class<?> ec) throws Exception {
Field field = ec.getDeclaredField("ENUM$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);
}
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()));
[RED, GREEN, BLUE]
[BLUE, GREEN, RED, BLUE]
GotoFinal
answer
How to create an instance of enum using reflection in java?
public enum Singleton {
INSTANCE("The one and only");
private String description;
private Singleton(String description) {
this.description = description;
}
@Override
public String toString() {
return description;
}
}
protected static Singleton createEnumValue(String name, int ordinal, String description) throws Exception {
Class<Singleton> monsterClass = Singleton.class;
Constructor<?> constructor = monsterClass.getDeclaredConstructors()[0];
constructor.setAccessible(true);
Field constructorAccessorField = Constructor.class.getDeclaredField("constructorAccessor");
constructorAccessorField.setAccessible(true);
sun.reflect.ConstructorAccessor ca = (sun.reflect.ConstructorAccessor) constructorAccessorField.get(constructor);
if (ca == null) {
Method acquireConstructorAccessorMethod = Constructor.class.getDeclaredMethod("acquireConstructorAccessor");
acquireConstructorAccessorMethod.setAccessible(true);
ca = (sun.reflect.ConstructorAccessor) acquireConstructorAccessorMethod.invoke(constructor);
}
Singleton enumValue = (Singleton) ca.newInstance(new Object[] { name, ordinal, description });
return enumValue;
}
protected static <E extends Enum<E>> void setFinalField(Class<E> ec, Field field, E e) throws NoSuchFieldException, IllegalAccessException {
Field modifiersField = Field.class.getDeclaredField("modifiers");
field.setAccessible(true);
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(ec, e);
}
System.out.println(Singleton.INSTANCE.toString());
// setting INSTANCE = theNewOne
Singleton theNewOne = createEnumValue(Singleton.INSTANCE.name(), Singleton.INSTANCE.ordinal(), "The new one!");
setFinalField(Singleton.class, Singleton.class.getDeclaredField(Singleton.INSTANCE.name()), theNewOne);
System.out.println(Singleton.INSTANCE.toString());
// setting enum array = [theNewOne]
clearFieldAccessors(getEnumsArrayField(Singleton.class));
setEnumsArray(Singleton.class, theNewOne);
System.out.println(Arrays.toString(Singleton.values()));
The one and only
The new one!
[The new one!]