简体   繁体   中英

How to read values of enum constants from annotation processor?

I'm working on a project, and my supervisors want me to be able to get the values of enum constants via an annotation processor. For example from the following enum definition:

public enum Animal {
    LION(5),
    GIRAFFE(7),
    ELEPHANT(2),

    private int value;

    Animal(int value) {
        this.value = value;
    }

    public int Value() {
        return value;
    }
}

They want me to compile an array of [5, 7, 2].

Note that because I am working within an annotation processor, I am using Element based reflection (not Class based reflection).

My reading of the VariableElement documentation leads me to believe this is impossible.

Note that not all final fields will have constant values. In particular, enum constants are not considered to be compile-time constants.

Does anyone know of a way to get this working?

Thank you for taking the time to read this! --Beka

What we ended up doing for this project is we compiled all of the enums before running the annotation processor. If a class has already been compiled before you run the annotation processor, it is possible to access information about it using Class based reflection.

Compiling the enums first was workable in this case because the enums' classes were passed to annotations on other classes (the enums are used to define some dropdowns).

Here is the code used to get the names of enum constants and their values. Where optionElem is the Element representing the enum class.

private <E extends Enum<E>> boolean tryAddOptionList(Element optionElem) {
    String className = optionElem.asType().toString();

    // Get the class.
    Class clazz = null;
    try {
      clazz = Class.forName(className);
    } catch (ClassNotFoundException e) {
      throw new IllegalArgumentException("OptionList Class: " + className + " is not available. " +
        "Make sure that it is available to the compiler.");
    }
    if (clazz == null) {
      return false;
    }

    // Get the getValue method.
    java.lang.reflect.Method getValueMethod = null;
    try {
      getValueMethod = clazz.getDeclaredMethod("getValue", new Class[] {});
    } catch (NoSuchMethodException e) {
      throw new IllegalArgumentException("Class: " + className + " must have a getValue() method.");
    }
    if (getValueMethod == null) {
      return false;
    }

    // Create a map of enum const names -> values.
    Map<String, String> namesToValues = Maps.newTreeMap();
    Object[] constants = clazz.getEnumConstants();
    for (Object constant : clazz.getEnumConstants()) {
        try {
          E enumConst = (E) constant;
          namesToValues.put(
            enumConst.name(),
            getValueMethod.invoke(enumConst, new Object [] {}).toString());
        } catch (Exception e) {}
    }
    // etc...
}

Here is the full pull request if you would like more context. The actually enum parsing is handled by the ComponentProcessor file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM