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