проверить перечисление
Проверка перечисления состоит в основном из трех API:
- Class.isEnum(): определить, является ли класс перечислением.
- Class.getEnumConstants(): получить константы перечисления в соответствии с порядком объявления в перечислении.
- java.lang.reflect.Field.isEnumConstant() Определяет, является ли поле перечислением
Пример выглядит следующим образом:
import java.util.Arrays;
import static java.lang.System.out;
enum Eon { HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC }
public class EnumConstants {
public static void main(String... args) {
try {
Class<?> c = (args.length == 0 ? Eon.class : Class.forName(args[0]));
out.format("Enum name: %s%nEnum constants: %s%n",
c.getName(), Arrays.asList(c.getEnumConstants()));
if (c == Eon.class)
out.format(" Eon.values(): %s%n",
Arrays.asList(Eon.values()));
// production code should handle this exception more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
}
результат операции:
$ java EnumConstants java.lang.annotation.RetentionPolicy
Enum name: java.lang.annotation.RetentionPolicy
Enum constants: [SOURCE, CLASS, RUNTIME]
$ java EnumConstants java.util.concurrent.TimeUnit
Enum name: java.util.concurrent.TimeUnit
Enum constants: [NANOSECONDS, MICROSECONDS,
MILLISECONDS, SECONDS,
MINUTES, HOURS, DAYS]
Поскольку перечисление также является классом, другая информация также может быть получена через API отражения поля, метода и конструктора:
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Member;
import java.util.List;
import java.util.ArrayList;
import static java.lang.System.out;
public class EnumSpy {
private static final String fmt = " %11s: %s %s%n";
public static void main(String... args) {
try {
Class<?> c = Class.forName(args[0]);
if (!c.isEnum()) {
out.format("%s is not an enum type%n", c);
return;
}
out.format("Class: %s%n", c);
Field[] flds = c.getDeclaredFields();
List<Field> cst = new ArrayList<Field>(); // enum constants
List<Field> mbr = new ArrayList<Field>(); // member fields
for (Field f : flds) {
if (f.isEnumConstant())
cst.add(f);
else
mbr.add(f);
}
if (!cst.isEmpty())
print(cst, "Constant");
if (!mbr.isEmpty())
print(mbr, "Field");
Constructor[] ctors = c.getDeclaredConstructors();
for (Constructor ctor : ctors) {
out.format(fmt, "Constructor", ctor.toGenericString(),
synthetic(ctor));
}
Method[] mths = c.getDeclaredMethods();
for (Method m : mths) {
out.format(fmt, "Method", m.toGenericString(),
synthetic(m));
}
// production code should handle this exception more gracefully
} catch (ClassNotFoundException x) {
x.printStackTrace();
}
}
private static void print(List<Field> lst, String s) {
for (Field f : lst) {
out.format(fmt, s, f.toGenericString(), synthetic(f));
}
}
private static String synthetic(Member m) {
return (m.isSynthetic() ? "[ synthetic ]" : "");
}
}
результат операции:
$ java EnumSpy java.lang.annotation.RetentionPolicy
Class: class java.lang.annotation.RetentionPolicy
Constant: public static final java.lang.annotation.RetentionPolicy
java.lang.annotation.RetentionPolicy.SOURCE
Constant: public static final java.lang.annotation.RetentionPolicy
java.lang.annotation.RetentionPolicy.CLASS
Constant: public static final java.lang.annotation.RetentionPolicy
java.lang.annotation.RetentionPolicy.RUNTIME
Field: private static final java.lang.annotation.RetentionPolicy[]
java.lang.annotation.RetentionPolicy. [ synthetic ]
Constructor: private java.lang.annotation.RetentionPolicy()
Method: public static java.lang.annotation.RetentionPolicy[]
java.lang.annotation.RetentionPolicy.values()
Method: public static java.lang.annotation.RetentionPolicy
java.lang.annotation.RetentionPolicy.valueOf(java.lang.String)
Установить поля на основе типа перечисления
Пример:
Consider application which needs to dynamically modify the trace level in a server application which normally does not allow this change during runtime. Assume the instance of the server object is available. The SetTrace example shows how code can translate the String representation of an enum into an enum type and retrieve and set the value of a field storing an enum.
import java.lang.reflect.Field;
import static java.lang.System.out;
enum TraceLevel { OFF, LOW, MEDIUM, HIGH, DEBUG }
class MyServer {
private TraceLevel level = TraceLevel.OFF;
}
public class SetTrace {
public static void main(String... args) {
TraceLevel newLevel = TraceLevel.valueOf(args[0]);
try {
MyServer svr = new MyServer();
Class<?> c = svr.getClass();
Field f = c.getDeclaredField("level");
f.setAccessible(true);
TraceLevel oldLevel = (TraceLevel)f.get(svr);
out.format("Original trace level: %s%n", oldLevel);
if (oldLevel != newLevel) {
f.set(svr, newLevel);
out.format(" New trace level: %s%n", f.get(svr));
}
// production code should handle these exceptions more gracefully
} catch (IllegalArgumentException x) {
x.printStackTrace();
} catch (IllegalAccessException x) {
x.printStackTrace();
} catch (NoSuchFieldException x) {
x.printStackTrace();
}
}
}
результат операции:
$ java SetTrace OFF
Original trace level: OFF
$ java SetTrace DEBUG
Original trace level: OFF
New trace level: DEBUG
Устранение неполадок
IllegalArgumentException возникает при попытке инициализировать тип перечисления или установить несовместимый тип перечисления в поле.
Пример: попытка инициализировать перечисляемый тип
IllegalArgumentException When Attempting to Instantiate an Enum Type
As has been mentioned, instantiation of enum types is forbidden. The EnumTrouble example attempts this.
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)
Пример: установка несовместимых типов перечисления
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)
Связанное Чтение