该Java教程是为JDK 8编写的。本页面描述的示例和实践不利用后续版本引入的改进,并可能使用不再可用的技术。
有关Java SE 9及以后版本中更新的语言功能的摘要,请参阅Java语言更改。
有关所有JDK版本的新功能、增强功能以及已删除或弃用选项的信息,请参阅JDK发行说明。
以下示例显示使用枚举类型可能遇到的问题。
如前所述,枚举类型的实例化是禁止的。
示例试图进行此操作。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("正在构建中%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("构造函数:%s%n", ctor.toGenericString()); ctor.setAccessible(true); ctor.newInstance(); } // 产品代码应更优雅地处理这些异常 } catch (InstantiationException x) { x.printStackTrace(); } catch (IllegalAccessException x) { x.printStackTrace(); } catch (InvocationTargetException x) { x.printStackTrace(); } } }
$ java EnumTrouble 构造函数:private Charge() Exception in thread "main" java.lang.IllegalArgumentException: 无法通过反射创建枚举对象 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 // 产品代码应更优雅地处理这些异常 } catch (NoSuchFieldException x) { x.printStackTrace(); } catch (IllegalAccessException x) { x.printStackTrace(); } } }
$ java EnumTroubleToo 在主线程中发生异常:java.lang.IllegalArgumentException: 无法将 E0 字段设置为 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)) // 兼容 else // 期望抛出 IllegalArgumentException