Java Enums — Elevator pitch

Learn
5 min readMay 16, 2021

Let us look at a basic enum.

enum Color {
WHITE,
BLACK
}

Type
A class essentially defines a type. All the instances of the class would be of a particular type. All instances of a String class would be a string. That is they would all have a sequence of characters, and you can do certain known operations on them like concatenation, upper-casing, lower-casing etc.

Enumerating a static list of values
Now, say you have a static list of operations that your system supports, and based on what you are asked to perform, you execute the respective operation. You can capture using int constants or String constants as follows.

public static final int OP_DEBIT = 1;
public static final int OP_CREDIT = 2;

Or

public static final String OP_DEBIT = “DEBIT”;
public static final String OP_CREDIT = “CREDIT”:

Or

enum Operation {
DEBIT,
CREDIT
}

What does the enum Operation buy you that the int constant and String constant approach did not?

It gives you type safety. With int constant approach, a client is expected to pass 1 to effect a debit and 2 to effect a credit. If a developer passed in 11 by mistake, the compiler would not recognize that there has been an error as it is still an int. Same reasoning for String constants too, say a developer passed in “DEBT” in place of “DEBIT”, compiler would not detect it as they are both strings.
However, if you were using enums and you typed in DEBT in place of DEBIT, compiler would immediately complain that it cannot understand DEBT which saves you a lot of pain as you get a chance to fix right at the point where you made the mistake. With string and int constant scenario, you are basically in the dark on the number of points at which these kinds of human errors might have happened and how they would manifest.
Type safety is not an esoteric concept. It is very practical. Your code is a huge degree safer. There are any number of reasons that you can have typos in your code and enums provide an easy to use mechanism to protect you.

Enums can be much more than indicator words

In the previous example, the enum was very simple, and each enum was just a word DEBIT / CREDIT. However, enums can hold entire state and behavior.

Understanding the syntax of Enums
Enums can be seen as classes that export enumerated instances of the class. The enum syntax has two portions — one portion representing the definition of the class, (with it’s state variables, it’s methods and the constructor) and the second portion with the instances of the class that was just defined using the constructor.
Top portion of the enum is the enumeration of instances, each instance is separated from the next by a comma, and you end the list with a semi-colon.
After this listing of enumeration constants is the definition of the enum which will have the ‘class’ definition — that is the state variables, and the method definitions.

Enum with state

enum Minister{
//Enumeration constants start
HomeMinister(55, “John Samuel),
ElecriticyMinister(68, “Richard Samson”)
;
// Class definition start
public int age;
public String name;
public Minister(int age, String name){
this.age = age;
this.name = name;
}
}

Above is an example of a Minister enum responsible for capturing say the ministers in the current government.

The class definition comes first before enumerating the instances when you think about it logically. But from a syntax perspective, the enumerations come before the definition of the class. When I write enums, I usually start with a semi-colon which would indicate zero enumeration instances to start with, and then go on to defining the definition of the class so that the compiler/ID will not complain about the syntax.

Enum with state and behavior

In addition to just the state, you can create enums which also have behavior. This means that the definition portion of the enum would have a method (or multiple methods) as well in addition to the state variables, and the client can invoke this method(s) on any of the enumeration constants. Method behavior is exactly the same across the different enumeration constants.

Enum with varying behavior per enumeration constant

What we have here is that each of the enumeration constants have their own custom behavior defined even while the method name is the same. How would this be achieved? Using an abstract method in the definition portion of the enum, and overriding this abstract method to have a specific implementation behavior per enumeration instance.

Let us take a look at an example of two banks, both of which are supposed to compute the interest. While that is common functionality, we have run into banks where each bank has it’s own computation rules. Let us treat that as a reasonable scenario to understand enums with varying behaviors per enumeration constant.

enum BankInterestComputer {
BankOne(8) {
@Override
public double computeInterest(int principal) {
int bankOneFactor = 2;
return principal * bankOneFactor * this.rate / 100;

},
BankTwo(10) {
@Override
public double computeInterest(int principal) {
int bankTwoFactor = 3;
return principal * bankTwoFactor * this.rate / 100;
}
;
public int rate;
BankInterestComputer(int rate) {
this.rate = rate;
}
public abstract double computeInterest(int principal);
}

These are just representational enums with just enough detail to present each of the aspects being discussed. This approach would have very well worked with huge functionalities spanning lot of state and lot of methods as well.

Enum is not just syntactic sugar for exporting instances of a class
Arguably, for someone who does not understand enums, he could just export these instances directly in the class definition. But, the slack with that approach is that if that class were directly approached, a client could create another instance that is not one of the enumerated ones.
Given that this discussion is around use cases where the details of these instances are known at compile time itself, enum is the tighter choice, and the choice that does not expose towards potential errors.

Be conscious about visibility for the enums

You don’t want to have enums that are relevant to one or two classes to be visible to the entire project with hundreds of classes, thus polluting the namespace of the enums. On the other hand, you do not want to repeat creating the same enums within multiple classes. However, if a enum is relevant only in the context of a single class, then the enum should be defined within the class itself.

To summarize, enums are good and not used as much is what I have felt. If you are seeing a lot of these kind of statements in your codebase, you can most likely replace these with well classified well named enums.

public static final int TYPE_XYZ = 1;

Get started there! And keep looking for opportunities to use these where appropriate!

--

--