In this tutorial we will see how to refactor an enum
. I was recently working on a small project that was using an enum
to manage some constants. But we had to change this enum
to a class
due to change of requirements.
Overview
Let’s say that a project was allowing users to choose from seven colors. But the requirements changed in due course of time and any color could be chosen. So in this situation an enum
cannot fulfill the requirement anymore. So we would need to change to class
. In the example below we would define an enum
Colors and then a usage class that has some typical use cases of enums
.
Classes before refactoring
Colors.java
A simple enum
with seven enums. If you are wondering why i have a comment after each enum read Keep formatting enum in IDE
package com.programtalk.learn.enumeration.refactor; public enum Colors { RED, // this is only for keeping the formatting ORANGE, // YELLOW, // GREEN, // BLUE, // INDIGO , // VIOLET; }
Example usage of Colors
This shows a typical usage of an enum. We are using it in an switch-case
and also using ==
to compare enums
.
package com.programtalk.learn.enumeration.refactor; public class UseColors { public void chooseAColor(Colors color ){ switch (color) { case BLUE: System.out.println("I have choosen BLUE Color"); break; case GREEN: case INDIGO: case ORANGE: case RED: case VIOLET: case YELLOW: System.out.println("I have choosen " + color + " Color"); break; default: break; } } public void doSomethingOnly4Yellow(Colors color){ if(Colors.YELLOW == color){ System.out.println("Yellow color was selected"); } } }
After Refactoring
Colors Class
So I refactored the enum to a class. So what did i do here?
- I kept the enums as constants in the Colors class. This i did so that i don’t have to change the code lines that refer to the constants. Colors.RED will still work.
- I used the factory method to create the instance of the Object
- I implemented the
equals()
andhashCode()
so that the objects are equal only when the color is the same.
package com.programtalk.learn.enumeration.refactored; import org.apache.commons.lang3.StringUtils; public class Colors { public static final Colors RED = Colors.create("RED"); public static final Colors ORANGE = Colors.create("ORANGE"); // public static final Colors YELLOW = Colors.create("YELLOW"); // public static final Colors GREEN = Colors.create("GREEN"); // public static final Colors BLUE = Colors.create("BLUE"); // public static final Colors INDIGO = Colors.create("INDIGO"); // public static final Colors VIOLET = Colors.create("VIOLET"); // private final String color; public static Colors create(String color) { if(StringUtils.isBlank(color)){ throw new IllegalStateException("color must not be blank"); } return new Colors(color); } private Colors(){ throw new IllegalStateException("Please use another constructor."); } private Colors(String color) { this.color = color; } public String getColor() { return color; } /** * It is important to have the equals and hashcode functions implemeted * */ @Override public int hashCode() { return 17 + color.hashCode(); } @Override public boolean equals(Object obj) { if(obj == null){ return false; } if(!(obj instanceof Colors)){ return false; } Colors otherColor = (Colors) obj; return StringUtils.equals(this.getColor(), otherColor.getColor()); } }
Example usage of Colors class
In the example I changed the following pieces of code
- In the
switch-case
I had to change to string constants - And the
==
has to be changed toequals()
package com.programtalk.learn.enumeration.refactored; public class UseColors { public void chooseAColor(Colors color ){ switch (color.getColor()) { case "BLUE": System.out.println("I have choosen BLUE Color"); break; case "GREEN": case "INDIGO": case "ORANGE" : case "RED" : case "VIOLET" : case "YELLOW" : System.out.println("I have choosen " + color + " Color"); break; default: break; } } /** * While refactoring take care that equals is replaced with equals() * @param color */ public void doSomethingOnly4YellowWrong( Colors color){ // doesnot show a compiler warning but may work only when you pass the Colors.YELLOW object if(Colors.YELLOW == color){ System.out.println("Yellow color was selected"); } } /** * While refactoring take care that equals is replaced with equals() * @param color */ public void doSomethingOnly4YellowCorrect( Colors color){ // this will always work if(Colors.YELLOW.equals(color)){ System.out.println("Yellow color was selected"); } } }