Search code examples
javaenumsinterfaceannotations

Accessing annotation of an enum referenced by an implemented interface


I am trying to access parameters of an annotation of an enum field that is referenced by an interface that is implemented by many enum classes. Something like this:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@interface MyAnnotation {
    String someValue();
}

interface CommonInterface {}

enum FirstEnum implements CommonInterface{
    @MyAnnotation(someValue = "abc")
    A;
}

enum SecondEnum implements CommonInterface{
    @MyAnnotation(someValue = "cde")
    B;
}

void foo(CommonInterface enumValue){
   String someValue; // get the parameter value
}

I found a way around this by adding methods to the common interface that return reflection information of the enum class, like this:

interface CommonInterface{
    Class<? extends CommonInterface> getEnumClass();
    String getName();
}

enum FirstEnum implements CommonInteface{
    @MyAnnotation(someValue = "abc")
    A;

    public Class<? extends CommonInteface> getEnumClass() {
        return getClass();
    }

    public String getName() {
        return name();
    }
}

void foo(CommonInterface enumValue){
    MyAnnotation myAnnotation = enumValue.getEnumClass().getField(enumValue.getName()).getAnnotation(MyAnnotation.class);
}

Is there a nicer way of doing the same thing? I saw some solutions where they recommend a wrapper enum class which takes the enum values referenced by the interface as constructor args. In my case that is not very feasible, because there will be many of these enums implementing the common interface and each will have many values, so maintaining it wouldn't be nice.

Thanks


Solution

  • You don't need to expose getEnumClass() via your CommonInterface, calling getClass() on the instance will always suffice. Likewise why call your method getName() why not just call it name() so it's implicitly implementation by Enum?

    You can just do something like this without any methods added to CommonInterface:

    void foo(CommonInterface enumValue) throws Exception {
        String name = enumValue.getClass().getMethod("name").invoke(enumValue).toString();
        MyAnnotation myAnnotation = enumValue.getClass().getField(name).getAnnotation(MyAnnotation.class);
        System.out.println(myAnnotation.someValue());
    }
    

    That's dangerous though because it assumes all implementations of CommonInterface are enums and therefore have a name() method. To make thinks "safer" in case you have a CommonInterface implementation which isn't an enum add the "name" method to CommonInterface:

    interface CommonInterface {
        String name();
    }
    

    And then your "foo" method becomes:

    void foo(CommonInterface enumValue) throws Exception {
        MyAnnotation myAnnotation = enumValue.getClass().getField(enumValue.name()).getAnnotation(MyAnnotation.class);
        System.out.println(myAnnotation.someValue());
    }