Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to supply Enum value to an annotation from a Constant in Java

I'm unable to use an Enum taken from a Constant as a parameter in an annotation. I get this compilation error: "The value for annotation attribute [attribute] must be an enum constant expression".

This is a simplified version of the code for the Enum:

public enum MyEnum {     APPLE, ORANGE } 

For the Annotation:

@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD }) public @interface MyAnnotation {     String theString();      int theInt();      MyEnum theEnum(); } 

And the class:

public class Sample {     public static final String STRING_CONSTANT = "hello";     public static final int INT_CONSTANT = 1;     public static final MyEnum MYENUM_CONSTANT = MyEnum.APPLE;      @MyAnnotation(theEnum = MyEnum.APPLE, theInt = 1, theString = "hello")     public void methodA() {      }      @MyAnnotation(theEnum = MYENUM_CONSTANT, theInt = INT_CONSTANT, theString = STRING_CONSTANT)     public void methodB() {      }  } 

The error shows up only in "theEnum = MYENUM_CONSTANT" over methodB. String and int constants are ok with the compiler, the Enum constant is not, even though it's the exact same value as the one over methodA. Looks to me like this is a missing feature in the compiler, because all three are obviously constants. There are no method calls, no strange use of classes, etc.

What I want to achieve is:

  • To use the MYENUM_CONSTANT in both the annotation and later in the code.
  • To stay type safe.

Any way to achieve these goals would be fine.

Edit:

Thanks all. As you say, it cannot be done. The JLS should be updated. I decided to forget about enums in annotations this time, and use regular int constants. As long as the int is assigned from a named constant, the values are bounded and it's "sort of" type safe.

It looks like this:

public interface MyEnumSimulation {     public static final int APPLE = 0;     public static final int ORANGE = 1; } ... public static final int MYENUMSIMUL_CONSTANT = MyEnumSimulation.APPLE; ... @MyAnnotation(theEnumSimulation = MYENUMSIMUL_CONSTANT, theInt = INT_CONSTANT, theString = STRING_CONSTANT) public void methodB() { ... 

And I can use MYENUMSIMUL_CONSTANT anywhere else in the code.

like image 353
user1118312 Avatar asked Nov 06 '12 14:11

user1118312


People also ask

How do you assign a value to the constant of an enum?

To hold the value of each constant you need to have an instance variable (generally, private). You cannot create an object of an enum explicitly so, you need to add a parameterized constructor to initialize the value(s). The initialization should be done only once.

Can we use const for enum?

Using const enum means that the code is completely virtual, and is never compiled to actual code. Smaller bundles, less code, simple change. It's a great addition and consideration to the TypeScript language and I'd highly encourage you to start using it!

How do you declare a constant in an enum in Java?

An enum is a special class that represents a group of constants. To create an enum, use the enum keyword (instead of class or interface), and separate the constants with a comma. values() method can be used to return all values present inside enum.

How do I convert an enum to a String in Java?

There are two ways to convert an Enum to String in Java, first by using the name() method of Enum which is an implicit method and available to all Enum, and second by using toString() method.


1 Answers

"All problems in computer science can be solved by another level of indirection" --- David Wheeler

Here it is:

Enum class:

public enum Gender {     MALE(Constants.MALE_VALUE), FEMALE(Constants.FEMALE_VALUE);      Gender(String genderString) {     }      public static class Constants {         public static final String MALE_VALUE = "MALE";         public static final String FEMALE_VALUE = "FEMALE";     } } 

Person class:

import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonSubTypes; import com.fasterxml.jackson.annotation.JsonTypeInfo; import static com.fasterxml.jackson.annotation.JsonTypeInfo.As; import static com.fasterxml.jackson.annotation.JsonTypeInfo.Id;  @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = Person.GENDER) @JsonSubTypes({     @JsonSubTypes.Type(value = Woman.class, name = Gender.Constants.FEMALE_VALUE),     @JsonSubTypes.Type(value = Man.class, name = Gender.Constants.MALE_VALUE) }) public abstract class Person { ... } 
like image 120
Ivan Hristov Avatar answered Sep 20 '22 09:09

Ivan Hristov