检查枚举

原文: https://docs.oracle.com/javase/tutorial/reflect/special/enumMembers.html

Reflection 提供了三个枚举特定的 API:

Class.isEnum()

Indicates whether this class represents an enum type

Class.getEnumConstants()

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() 检索枚举中的常量有序列表。

  1. import java.util.Arrays;
  2. import static java.lang.System.out;
  3. enum Eon { HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC }
  4. public class EnumConstants {
  5. public static void main(String... args) {
  6. try {
  7. Class<?> c = (args.length == 0 ? Eon.class : Class.forName(args[0]));
  8. out.format("Enum name: %s%nEnum constants: %s%n",
  9. c.getName(), Arrays.asList(c.getEnumConstants()));
  10. if (c == Eon.class)
  11. out.format(" Eon.values(): %s%n",
  12. Arrays.asList(Eon.values()));
  13. // production code should handle this exception more gracefully
  14. } catch (ClassNotFoundException x) {
  15. x.printStackTrace();
  16. }
  17. }
  18. }

输出样例如下。用户输入以斜体显示。

  1. $ java EnumConstants java.lang.annotation.RetentionPolicy
  2. Enum name: java.lang.annotation.RetentionPolicy
  3. Enum constants: [SOURCE, CLASS, RUNTIME]
  1. $ java EnumConstants java.util.concurrent.TimeUnit
  2. Enum name: java.util.concurrent.TimeUnit
  3. Enum constants: [NANOSECONDS, MICROSECONDS,
  4. MILLISECONDS, SECONDS,
  5. MINUTES, HOURS, DAYS]

此示例还显示 Class.getEnumConstants() 返回的值与通过在枚举类型上调用values()返回的值相同。

  1. $ java EnumConstants
  2. Enum name: Eon
  3. Enum constants: [HADEAN, ARCHAEAN,
  4. PROTEROZOIC, PHANEROZOIC]
  5. Eon.values(): [HADEAN, ARCHAEAN,
  6. PROTEROZOIC, PHANEROZOIC]

由于枚举是类,因此可以使用此跟踪的字段字段,方法构造器部分中描述的相同 Reflection API 获取其他信息。 EnumSpy 代码说明了如何使用这些 API 获取有关枚举声明的其他信息。该示例使用 Class.isEnum() 来限制检查的类集。它还使用 Field.isEnumConstant() 来区分枚举常量与枚举声明中的其他字段(并非所有字段都是枚举常量)。

  1. import java.lang.reflect.Constructor;
  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.Method;
  4. import java.lang.reflect.Member;
  5. import java.util.List;
  6. import java.util.ArrayList;
  7. import static java.lang.System.out;
  8. public class EnumSpy {
  9. private static final String fmt = " %11s: %s %s%n";
  10. public static void main(String... args) {
  11. try {
  12. Class<?> c = Class.forName(args[0]);
  13. if (!c.isEnum()) {
  14. out.format("%s is not an enum type%n", c);
  15. return;
  16. }
  17. out.format("Class: %s%n", c);
  18. Field[] flds = c.getDeclaredFields();
  19. List<Field> cst = new ArrayList<Field>(); // enum constants
  20. List<Field> mbr = new ArrayList<Field>(); // member fields
  21. for (Field f : flds) {
  22. if (f.isEnumConstant())
  23. cst.add(f);
  24. else
  25. mbr.add(f);
  26. }
  27. if (!cst.isEmpty())
  28. print(cst, "Constant");
  29. if (!mbr.isEmpty())
  30. print(mbr, "Field");
  31. Constructor[] ctors = c.getDeclaredConstructors();
  32. for (Constructor ctor : ctors) {
  33. out.format(fmt, "Constructor", ctor.toGenericString(),
  34. synthetic(ctor));
  35. }
  36. Method[] mths = c.getDeclaredMethods();
  37. for (Method m : mths) {
  38. out.format(fmt, "Method", m.toGenericString(),
  39. synthetic(m));
  40. }
  41. // production code should handle this exception more gracefully
  42. } catch (ClassNotFoundException x) {
  43. x.printStackTrace();
  44. }
  45. }
  46. private static void print(List<Field> lst, String s) {
  47. for (Field f : lst) {
  48. out.format(fmt, s, f.toGenericString(), synthetic(f));
  49. }
  50. }
  51. private static String synthetic(Member m) {
  52. return (m.isSynthetic() ? "[ synthetic ]" : "");
  53. }
  54. }
  1. $ java EnumSpy java.lang.annotation.RetentionPolicy
  2. Class: class java.lang.annotation.RetentionPolicy
  3. Constant: public static final java.lang.annotation.RetentionPolicy
  4. java.lang.annotation.RetentionPolicy.SOURCE
  5. Constant: public static final java.lang.annotation.RetentionPolicy
  6. java.lang.annotation.RetentionPolicy.CLASS
  7. Constant: public static final java.lang.annotation.RetentionPolicy
  8. java.lang.annotation.RetentionPolicy.RUNTIME
  9. Field: private static final java.lang.annotation.RetentionPolicy[]
  10. java.lang.annotation.RetentionPolicy. [ synthetic ]
  11. Constructor: private java.lang.annotation.RetentionPolicy()
  12. Method: public static java.lang.annotation.RetentionPolicy[]
  13. java.lang.annotation.RetentionPolicy.values()
  14. Method: public static java.lang.annotation.RetentionPolicy
  15. 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的其他字段,这些字段不是枚举常量。

  1. $ java EnumSpy java.util.concurrent.TimeUnit
  2. Class: class java.util.concurrent.TimeUnit
  3. Constant: public static final java.util.concurrent.TimeUnit
  4. java.util.concurrent.TimeUnit.NANOSECONDS
  5. Constant: public static final java.util.concurrent.TimeUnit
  6. java.util.concurrent.TimeUnit.MICROSECONDS
  7. Constant: public static final java.util.concurrent.TimeUnit
  8. java.util.concurrent.TimeUnit.MILLISECONDS
  9. Constant: public static final java.util.concurrent.TimeUnit
  10. java.util.concurrent.TimeUnit.SECONDS
  11. Constant: public static final java.util.concurrent.TimeUnit
  12. java.util.concurrent.TimeUnit.MINUTES
  13. Constant: public static final java.util.concurrent.TimeUnit
  14. java.util.concurrent.TimeUnit.HOURS
  15. Constant: public static final java.util.concurrent.TimeUnit
  16. java.util.concurrent.TimeUnit.DAYS
  17. Field: static final long java.util.concurrent.TimeUnit.C0
  18. Field: static final long java.util.concurrent.TimeUnit.C1
  19. Field: static final long java.util.concurrent.TimeUnit.C2
  20. Field: static final long java.util.concurrent.TimeUnit.C3
  21. Field: static final long java.util.concurrent.TimeUnit.C4
  22. Field: static final long java.util.concurrent.TimeUnit.C5
  23. Field: static final long java.util.concurrent.TimeUnit.C6
  24. Field: static final long java.util.concurrent.TimeUnit.MAX
  25. Field: private static final java.util.concurrent.TimeUnit[]
  26. java.util.concurrent.TimeUnit. [ synthetic ]
  27. Constructor: private java.util.concurrent.TimeUnit()
  28. Constructor: java.util.concurrent.TimeUnit
  29. (java.lang.String,int,java.util.concurrent.TimeUnit)
  30. [ synthetic ]
  31. Method: public static java.util.concurrent.TimeUnit
  32. java.util.concurrent.TimeUnit.valueOf(java.lang.String)
  33. Method: public static java.util.concurrent.TimeUnit[]
  34. java.util.concurrent.TimeUnit.values()
  35. Method: public void java.util.concurrent.TimeUnit.sleep(long)
  36. throws java.lang.InterruptedException
  37. Method: public long java.util.concurrent.TimeUnit.toNanos(long)
  38. Method: public long java.util.concurrent.TimeUnit.convert
  39. (long,java.util.concurrent.TimeUnit)
  40. Method: abstract int java.util.concurrent.TimeUnit.excessNanos
  41. (long,long)
  42. Method: public void java.util.concurrent.TimeUnit.timedJoin
  43. (java.lang.Thread,long) throws java.lang.InterruptedException
  44. Method: public void java.util.concurrent.TimeUnit.timedWait
  45. (java.lang.Object,long) throws java.lang.InterruptedException
  46. Method: public long java.util.concurrent.TimeUnit.toDays(long)
  47. Method: public long java.util.concurrent.TimeUnit.toHours(long)
  48. Method: public long java.util.concurrent.TimeUnit.toMicros(long)
  49. Method: public long java.util.concurrent.TimeUnit.toMillis(long)
  50. Method: public long java.util.concurrent.TimeUnit.toMinutes(long)
  51. Method: public long java.util.concurrent.TimeUnit.toSeconds(long)
  52. Method: static long java.util.concurrent.TimeUnit.x(long,long,long)