Java Reflection for Enums

1. Overview

An enum is a language construct that is used to define type-safe enumerations which can be used when a fixed set of named values is desired. All enums implicitly extend java.lang.Enum. Enumsmay contain one or more enum constants, which define unique instances of the enum type. An enum declaration defines an enum type which is very similar to a class in that it may have members such as fields, methods, and constructors (with some restrictions).
Since enums are classes, reflection has no need to define an explicit java.lang.reflect.Enum class.

2. The Reflection APIs to Enums

  • Class.isEnum()
  • Class.getEnumConstants()
  • java.lang.reflect.Field.isEnumConstant()
Most reflective operations involving enums are the same as any other class or member. For example, enum constants are implemented as public static final fields on the enum. T

3. The Reflection Enum APIs Examples

Let's discuss show how to use Class and java.lang.reflect.Field with enums with examples.
  1. Examining Enums - illustrates how to retrieve an enum's constants and any other fields, constructors, and methods
  2. Getting and Setting Fields with Enum Types - shows how to set and get fields with an enum constant value

3.1 Examining Enums

Reflection provides three enum-specific APIs:
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 declaredjava.lang.reflect.Field.isEnumConstant() - Indicates whether this field represents an element of an enumerated type

Class.getEnumConstants() API Example

Sometimes it is necessary to dynamically retrieve the list of enum constants; in non-reflective code this is accomplished by invoking the implicitly declared static method values() on the enum. If an instance of an enum type is not available the only way to get a list of the possible values is to invoke Class.getEnumConstants() since it is impossible to instantiate an enum type.
Given a fully qualified name, the EnumConstants example shows how to retrieve an ordered list of constants in an enum using Class.getEnumConstants().
package com.javaguides.reflection.enums;

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) {
  Class<?> c = Eon.class;
  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()));
 }
}
Output:
Enum name:  com.javaguides.reflection.enums.Eon
Enum constants:  [HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC]
  Eon.values():  [HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC]
Since enums are classes, other information may be obtained using the same Reflection APIs described in the Fields, Methods, and Constructors posts of this trail.
The below example illustrates how to use these APIs to get additional information about the enum's declaration. The example uses Class.isEnum() to restrict the set of classes examined. It also uses Field.isEnumConstant() to distinguish enum constants from other fields in the enum declaration (not all fields are enum constants).

Class.isEnum() and Field.isEnumConstant() API Example

package com.javaguides.reflection.enums;

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;

enum Status {
 OPEN,INPROGRESS,FAIL,COMPLETED,RESOLVED,REVIEWED,CLOSED;
}

public class EnumSpy {
 private static final String fmt = "  %11s:  %s %s%n";

 public static void main(String... args) {
  try {
   Class<?> c = Class.forName("com.javaguides.reflection.enums.Status");
   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 ]" : "");
 }
}
Output:
Class:  class com.javaguides.reflection.enums.Status
     Constant:  public static final com.javaguides.reflection.enums.Status com.javaguides.reflection.enums.Status.OPEN 
     Constant:  public static final com.javaguides.reflection.enums.Status com.javaguides.reflection.enums.Status.INPROGRESS 
     Constant:  public static final com.javaguides.reflection.enums.Status com.javaguides.reflection.enums.Status.FAIL 
     Constant:  public static final com.javaguides.reflection.enums.Status com.javaguides.reflection.enums.Status.COMPLETED 
     Constant:  public static final com.javaguides.reflection.enums.Status com.javaguides.reflection.enums.Status.RESOLVED 
     Constant:  public static final com.javaguides.reflection.enums.Status com.javaguides.reflection.enums.Status.REVIEWED 
     Constant:  public static final com.javaguides.reflection.enums.Status com.javaguides.reflection.enums.Status.CLOSED 
        Field:  private static final com.javaguides.reflection.enums.Status[] com.javaguides.reflection.enums.Status.ENUM$VALUES [ synthetic ]
  Constructor:  private com.javaguides.reflection.enums.Status(java.lang.String,int) 
       Method:  public static com.javaguides.reflection.enums.Status[] com.javaguides.reflection.enums.Status.values() 
       Method:  public static com.javaguides.reflection.enums.Status com.javaguides.reflection.enums.Status.valueOf(java.lang.String) 

3.2 Getting and Setting Fields with Enum Types

Fields which store enums are set and retrieved as any other reference type, using Field.set() and Field.get(). For more information on accessing fields, see the Java Reflection for Fields post.
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.
package com.javaguides.reflection.enums;

import static java.lang.System.out;

import java.lang.reflect.Field;

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("DEBUG"); 

  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();
  }
 }
}
Output:
Original trace level:  OFF
    New  trace level:  DEBUG

4. Reference

5. Related Posts

Comments