Home » Java » Core Java » Featured enum instead of switch

About Alexander Radzin

Alexander Radzin
Alex is an experienced software engineer coding java and JVM based languages and technologies since 2000. Besides his work at the office he develops his own open source project at github and contributes code to other projects. Actively participated in StackOverflow community during several years.

Featured enum instead of switch

Problem and  its solution

Switch/case is the common control structure implemented in most imperative programming languages. Switch is considered more readable than series of if/else.

Here is a simple example:

// Switch with int literal
switch (c) {
  case 1: one(); break;
  case 2: two(); break;
  case 3: three(); break;
  default: throw new UnsupportedOperationException(String.format("Operation %d is not supported", c));
}

Here is the list of the main problems in this code:

  1. Relationship between int literals (1, 2, 3) and executed code is not obvious.
  2. If one of the values (e.g. 2) becomes not supported anymore and this switch is not updated accordingly it will contain  forever the unused code.
  3. If new possible value of c (e.g. 4) is introduced and the switch is not updated accordingly the code will probably throw UnsupportedOperationException at runtime without any compile time notifications.
  4. Such switch structure tends to be duplicated several times in code that makes problems 2 and 3 even more complicated. 

The first simplest fix can be done by using int constants instead of literals. First, let’s define constants:

private static int ONE = 1;
private static int TWO = 2;
private static int THREE = 3;

Now the code will look like this:

switch (c) {
  case ONE: one(); break;
  case TWO: two(); break;
  case THREE: three(); break;
  default: throw new UnsupportedOperationException(String.format("Operation %d is not supported", c));
}

(Obviously in real life the names of the constants must be self descriptive)

This snippet is more readable but all other disadvantages are still relevant. The next attempt to improve the initial code snippet uses enums introduced to Java language in version 5 in 2004. Let’s define the followingenum:

enum Action {ONE, TWO, THREE}

Now the switch snippet will be slightly changed:

Action a = ...
switch (a) {
  case ONE: one(); break;
  case TWO: two(); break;
  case THREE: three(); break;
  default: throw new UnsupportedOperationException(String.format("Operation %s is not supported", a));
}

This code is a little bit better: it will produce compilation error if one of the elements is removed fromenum Action. However, it will not cause compilation error if additional element is added to enum Action. Some IDEs or static code analysis tools may produce warning in this case, but who is paying attention to warnings? Fortunately enum can declare abstract method that has to be implemented by each element:

enum Action {
  ONE { @Override public void action() { } }, 
  TWO { @Override public void action() { } }, 
  THREE { @Override public void action() { } }, 
  public abstract void action();
}

Now the switch statement can be replaced by single line:

Action a = ...
a.action();

This solution does not have any of disadvantages enumerated above:

  1. It is readable. The method is “attached” to enum element; one can write as many javadoc as it is needed if method meaning is unclear. The code that calls method is trivial: what can be simpler than method invocation?
  2. There is no way to removeenumconstant without removing the implementation, so no unused code will remain if some functionality is no longer relevant.
  3. Newenumelement cannot be added without implementation of method action(). Code without implementation can’t be compiled. 
  4. If several actions are required they all can be implemented in enum. As we already mentioned the code that calls specific function is trivial, so now there is no code duplication. 

Conclusion

Although switch/case structure is well known and widely used in various programming languages its usage may cause a lot of problems. Solution that uses  java enums and described above does not have these disadvantages. The nextarticle from this series shows how to extend functionality of existing enum.

Published on Java Code Geeks with permission by Alexander Radzin, partner at our JCG program. See the original article here: Featured enum instead of switch

Opinions expressed by Java Code Geeks contributors are their own.

(+1 rating, 1 votes)
You need to be a registered member to rate this.
9 Comments Views Tweet it!
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

9
Leave a Reply

avatar
4 Comment threads
5 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
6 Comment authors
GarryKrishnaAlexander RadzinShane BenMdzaebel Recent comment authors

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  Subscribe  
newest oldest most voted
Notify of
hamda
Guest
hamda

how we can instanciate the Action enumeration ?
could you please give an example for the same?
Thanks

Shane Ben
Member
msn734506700

Action.ONE

Mdzaebel
Guest
Marc Dzaebel

Java 12 will improve switch syntax (https://dzone.com/articles/jdk-12-switch-statementsexpressions-in-action). If we do, what you intend, it might be easier to use:
enum Action implements Runnable {
ONE { @Override public void run() { } },
TWO { @Override public void run() { } },
THREE { @Override public void run() { } };
}

Note also, in your example, there is a comma instead of a semicolon, that make it uncompilable.

Krishna
Guest
Krishna

Interesting idea, but if we want to tie the action to the enum, why are we even using enum, why not create a base class and implement the concrete sub classes and call the action item on it?

Garry
Guest
Garry

I frequently have cases where I reference an ENUM but do different things depending on the context. This would work fine in cases where the ENUM only serves one limited and universal purpose. Otherwise I would find myself ignoring the method and using SWITCH statements like I do now. And I DO look for compilers warnings whenever I change an ENUM because it was an ENUM that was changed (pretty much only time I do actually).