Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Constant expressions from an Enum

Is there any way of converting an enum into a constant expression? I want my switch operator to choose among the values of an enum, but I got a compile error "case expressions must be constant expressions", so I tried to declare it in a variable:

final int REG = MyEnum.REG.getIndex().intValue();

switch (service.getIndex()) {

case REG:

But I still get the same error. According to Oracle's documentation http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28

A compile-time constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

•Literals of primitive type and literals of type String

So it isn't working because I'm not using a literal. I think I will have to declare it as:

final int REG = 8;

But it'd be much better to link it to the enum. Is there any way of doing this?

EDIT

Turns out I don't need to use any final variable. It is just as simple as:

switch (service) {

case REG:

It didn't occur to me till I saw Andrea's comment. Thanks for your answers.

like image 305
Luis Sep Avatar asked May 08 '13 10:05

Luis Sep


People also ask

Can an enum be constant?

Because they are constants, the names of an enum type's fields are in uppercase letters. You should use enum types any time you need to represent a fixed set of constants.

Is it better to use enum or constant?

Enums are lists of constants. When you need a predefined list of values which do represent some kind of numeric or textual data, you should use an enum. You should always use enums when a variable (especially a method parameter) can only take one out of a small set of possible values.

What does enum valueOf return?

valueOf. Returns the enum constant of the specified enum type with the specified name. The name must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.)

How do you convert a string value to a specific enum type in C#?

TryParse() method converts the string representation of enum member name or numeric value to an equivalent enum object. The Enum. TryParse() method returns a boolean to indicate whether the specified string is converted to enum or not. Returns true if the conversion succeeded; otherwise, returns false .


1 Answers

If possible, modify your getIndex() method so that it returns an enum instead of an integer. If this is not possible, you need to map the index to an enum element:

Given the following enum:

public enum Index {
   ONE,
   TWO,
   THREE
}

you can map your index to an enum element by using

Index.values()[index]

Given your method Integer getIndex(), you can then do something like

switch(Index.values()[getIndex()])
    case ONE : ... 
       break;

    case TWO : ...
       break;

    case THREE : ...
       break;
}

Note that this might throw an ArrayIndexOutOfBoundsException if you try to access an index within the enum which is larger than the number of enum elements (e.g. in the sample above, if getIndex() returns a value > 2).


I would encapsulate the expression Index.values()[getIndex()] into an enum method like valueOf(int index), similar to the default valueOf(String s). You can then also handle the valid array index check there (and for example return a special enum value if the index is out of range). Similarly, you can then also convert discrete values which have special meanings:

public enum Index {
   ZERO,
   ONE,
   TWO,
   THREE,
   REG,
   INVALID;


   public static Index valueOf(int index) {

       if (index == 8) {
          return REG;
       }

       if (index >= values().length) {
          return INVALID;
       }

       return values()[index];
   }
}

This is an example only - in any case, it generally depends on the range of values you get from your getIndex() method, and how you want to map them to the enum elements.

You can then use it like

switch(Index.valueOf(service.getIndex())) {
   case ZERO : ... break;
   ...
   case REG : ... break;
   ...
}

See also Cast Int to enum in Java for some additional information (especially the hint that values() is an expensive operation since it needs to return a copy of the array each time it is called).

like image 193
Andreas Fester Avatar answered Oct 05 '22 23:10

Andreas Fester