检查枚举
原文: https://docs.oracle.com/javase/tutorial/reflect/special/enumMembers.html
Reflection 提供了三个枚举特定的 API:
Indicates whether this class represents an enum type
Retrieves the list of enum constants defined by the enum in the order they’re declared
java.lang.reflect.Field.isEnumConstant()
Indicates whether this field represents an element of an enumerated type
有时需要动态检索枚举常量列表;在非反射代码中,这是通过在枚举上调用隐式声明的静态方法 values()
来实现的。如果枚举类型的实例不可用,获取可能值列表的唯一方法是调用 Class.getEnumConstants()
,因为无法实例化枚举类型。
给定完全限定名称, EnumConstants
示例显示如何使用 Class.getEnumConstants()
检索枚举中的常量有序列表。
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]
此示例还显示 Class.getEnumConstants()
返回的值与通过在枚举类型上调用values()
返回的值相同。
$ java EnumConstants
Enum name: Eon
Enum constants: [HADEAN, ARCHAEAN,
PROTEROZOIC, PHANEROZOIC]
Eon.values(): [HADEAN, ARCHAEAN,
PROTEROZOIC, PHANEROZOIC]
由于枚举是类,因此可以使用此跟踪的字段字段,方法和构造器部分中描述的相同 Reflection API 获取其他信息。 EnumSpy
代码说明了如何使用这些 API 获取有关枚举声明的其他信息。该示例使用 Class.isEnum()
来限制检查的类集。它还使用 Field.isEnumConstant()
来区分枚举常量与枚举声明中的其他字段(并非所有字段都是枚举常量)。
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)
输出显示 java.lang.annotation.RetentionPolicy
的声明仅包含三个枚举常量。枚举常量显示为public static final
字段。字段,构造器和方法是编译器生成的。 $VALUES
字段与values()
方法的实现有关。
Note: For various reasons, including support for evolution of the enum type, the declaration order of enum constants is important. Class.getFields()
and Class.getDeclaredFields()
do not make any guarantee that the order of the returned values matches the order in the declaring source code. If ordering is required by an application, use Class.getEnumConstants()
.
java.util.concurrent.TimeUnit
的输出表明可能存在更复杂的枚举。此类包括几个方法以及声明为static final
的其他字段,这些字段不是枚举常量。
$ java EnumSpy java.util.concurrent.TimeUnit
Class: class java.util.concurrent.TimeUnit
Constant: public static final java.util.concurrent.TimeUnit
java.util.concurrent.TimeUnit.NANOSECONDS
Constant: public static final java.util.concurrent.TimeUnit
java.util.concurrent.TimeUnit.MICROSECONDS
Constant: public static final java.util.concurrent.TimeUnit
java.util.concurrent.TimeUnit.MILLISECONDS
Constant: public static final java.util.concurrent.TimeUnit
java.util.concurrent.TimeUnit.SECONDS
Constant: public static final java.util.concurrent.TimeUnit
java.util.concurrent.TimeUnit.MINUTES
Constant: public static final java.util.concurrent.TimeUnit
java.util.concurrent.TimeUnit.HOURS
Constant: public static final java.util.concurrent.TimeUnit
java.util.concurrent.TimeUnit.DAYS
Field: static final long java.util.concurrent.TimeUnit.C0
Field: static final long java.util.concurrent.TimeUnit.C1
Field: static final long java.util.concurrent.TimeUnit.C2
Field: static final long java.util.concurrent.TimeUnit.C3
Field: static final long java.util.concurrent.TimeUnit.C4
Field: static final long java.util.concurrent.TimeUnit.C5
Field: static final long java.util.concurrent.TimeUnit.C6
Field: static final long java.util.concurrent.TimeUnit.MAX
Field: private static final java.util.concurrent.TimeUnit[]
java.util.concurrent.TimeUnit. [ synthetic ]
Constructor: private java.util.concurrent.TimeUnit()
Constructor: java.util.concurrent.TimeUnit
(java.lang.String,int,java.util.concurrent.TimeUnit)
[ synthetic ]
Method: public static java.util.concurrent.TimeUnit
java.util.concurrent.TimeUnit.valueOf(java.lang.String)
Method: public static java.util.concurrent.TimeUnit[]
java.util.concurrent.TimeUnit.values()
Method: public void java.util.concurrent.TimeUnit.sleep(long)
throws java.lang.InterruptedException
Method: public long java.util.concurrent.TimeUnit.toNanos(long)
Method: public long java.util.concurrent.TimeUnit.convert
(long,java.util.concurrent.TimeUnit)
Method: abstract int java.util.concurrent.TimeUnit.excessNanos
(long,long)
Method: public void java.util.concurrent.TimeUnit.timedJoin
(java.lang.Thread,long) throws java.lang.InterruptedException
Method: public void java.util.concurrent.TimeUnit.timedWait
(java.lang.Object,long) throws java.lang.InterruptedException
Method: public long java.util.concurrent.TimeUnit.toDays(long)
Method: public long java.util.concurrent.TimeUnit.toHours(long)
Method: public long java.util.concurrent.TimeUnit.toMicros(long)
Method: public long java.util.concurrent.TimeUnit.toMillis(long)
Method: public long java.util.concurrent.TimeUnit.toMinutes(long)
Method: public long java.util.concurrent.TimeUnit.toSeconds(long)
Method: static long java.util.concurrent.TimeUnit.x(long,long,long)