相关文章推荐
茫然的风衣  ·  Java SE 6 — 更好的 ...·  4 月前    · 
英俊的水桶  ·  在Visual Studio ...·  1 年前    · 
有胆有识的炒饭  ·  提取数据 - Tableau·  1 年前    · 
  • 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]

    因为枚举也是一个类,所以也可以通过Field,Method,Constructor的反射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);
    		    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)
  • 反射基础之Class
  • 反射基础之Field
  • 反射基础之Constructor
  • 反射基础之Array
  • 反射基础之Enum
  • 反射基础之Method
  • 104.2k
    粉丝