该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