Java 教程是为 JDK 8 编写的。本页中描述的示例和实践未利用在后续版本中引入的改进。
以下示例显示使用枚举类型时可能遇到的问题。
如前所述,禁止实例化枚举类型。
示例尝试此操作。EnumTrouble
import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import static java.lang.System.out; enum Charge { POSITIVE, NEGATIVE, NEUTRAL; Charge() { out.format("under construction%n"); } } public class EnumTrouble { public static void main(String... args) { try { Class<?> c = Charge.class; Constructor[] ctors = c.getDeclaredConstructors(); for (Constructor ctor : ctors) { out.format("Constructor: %s%n", ctor.toGenericString()); ctor.setAccessible(true); ctor.newInstance(); } // production code should handle these exceptions more gracefully } catch (InstantiationException x) { x.printStackTrace(); } catch (IllegalAccessException x) { x.printStackTrace(); } catch (InvocationTargetException x) { x.printStackTrace(); } } }
$ java EnumTrouble Constructor: private Charge() Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects at java.lang.reflect.Constructor.newInstance(Constructor.java:511) at EnumTrouble.main(EnumTrouble.java:22)
Class.isEnum()
以确定该类是否为枚举。
存储枚举的字段集使用适当的枚举类型。(实际上,必须使用兼容类型设置 任何 类型的字段。)
示例会产生预期的错误。EnumTroubleToo
import java.lang.reflect.Field; enum E0 { A, B } enum E1 { A, B } class ETest { private E0 fld = E0.A; } public class EnumTroubleToo { public static void main(String... args) { try { ETest test = new ETest(); Field f = test.getClass().getDeclaredField("fld"); f.setAccessible(true); f.set(test, E1.A); // IllegalArgumentException // production code should handle these exceptions more gracefully } catch (NoSuchFieldException x) { x.printStackTrace(); } catch (IllegalAccessException x) { x.printStackTrace(); } } }
$ java EnumTroubleToo Exception in thread "main" java.lang.IllegalArgumentException: Can not set E0 field ETest.fld to E1 at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException (UnsafeFieldAccessorImpl.java:146) at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException (UnsafeFieldAccessorImpl.java:150) at sun.reflect.UnsafeObjectFieldAccessorImpl.set (UnsafeObjectFieldAccessorImpl.java:63) at java.lang.reflect.Field.set(Field.java:657) at EnumTroubleToo.main(EnumTroubleToo.java:16)
X
的字段设置为类型 Y
的值的尝试,只有在以下语句成立时才能成功:
X.class.isAssignableFrom(Y.class) == true
if (f.getType().isAssignableFrom(E0.class)) // compatible else // expect IllegalArgumentException