
What are Enums?
Enums or Enumerations are special Classes that can create only a limited number of predefined objects. This is useful in the instances where you know exactly how many objects are needed to be available. Attempting to create an object which is not defined inside the Enum Class would cause an error. So, the object limitation is always guaranteed!
Creating an Enum Class
For creating a new Enum, select File → New → Enum in Eclipse and give it an appropriate name.
This Enum Class has any feature available in an ordinary Class. You can add variables and methods to it. It can have a main() method as well.
The only extra thing here is: you have to specify the names of the objects that you need in the beginning of the Enum, that is, below the Enum declaration sentence.
For example, suppose I want to create an Enum for the four seasons.
1 2 3 |
public enum Seasons { SPRING, SUMMER, AUTUMN, WINTER; } |
There are four objects in this Enum called SPRING, SUMMER, AUTUMN and WINTER. These objects are called as “Enum constants” because, they remain unchanged when the Enum is used in another Class.
The list of Enum objects ends with the semicolon. After that semicolon, you can add the variables and methods to your Enum.
Now I add few extra methods and a String member variable. I’ll add a main() method as well.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
public enum Seasons { //Enum Constants SPRING, SUMMER, AUTUMN, WINTER; private String seasonDetails="None"; //Example method1 public void setSeasonDetails(String details){ this.seasonDetails = details; } //Example method2 public void getInfo(){ if (this.equals(SPRING)){ System.out.println("This is the spring. \nmore information:\n"+seasonDetails+"\n"); } else if (this.equals(SUMMER)){ System.out.println("This is the summer.\nmore information:\n"+seasonDetails+"\n"); } else if (this.equals(AUTUMN)){ System.out.println("This is the autumn.\nmore information:\n"+seasonDetails+"\n"); } else{ System.out.println("This is the cold winter.\nmore information:\n"+seasonDetails+"\n"); } } //Example static method public static Seasons changeSeason(int seasonNo){ if (seasonNo==0) return SPRING; if (seasonNo==1) return SUMMER; if (seasonNo==2) return AUTUMN; //returns winter season object if any number //other than 0,1 or 2 is given as the parameter return WINTER; } //main() method public static void main(String[] args){ //first, Enum object AUTUMN is created and called //its getInfo() method. Seasons mySeason = Seasons.AUTUMN; mySeason.getInfo(); //Call the static method changSeason() and change the //reference of mySeason to a SUMMER object. mySeason = Seasons.changeSeason(1); mySeason.getInfo(); //set the season details of the SUMMER object. mySeason.setSeasonDetails("this is a test!"); mySeason.getInfo(); } } |
Output:
1 2 3 4 5 6 7 8 9 10 11 |
This is the autumn. more information: None This is the summer. more information: None This is the summer. more information: this is a test! |
I think you can easily understand how the code works by just looking at it. All I wanted to show is enums are not much different from usual Classes and Enum objects are quite same as the normal objects.
There’s an important point you must notice. We don’t use the keyword “new” to make an Enum object.
1 |
Seasons mySeason = new Seasons() //WRONG!!! |
What we do is this:-
1 |
Seasons mySeason = Seasons.AUTUMN; //Correct! |
There’s a static method in an Enum called values() which will return an array of all the objects in the Enum. We can use this to print all the objects inside the Enum like this, by using a for each loop.
In the main() method,
1 2 3 |
for(Seasons s:Seasons.values()){ System.out.println(s); } |
Output:
1 2 3 4 |
SPRING SUMMER AUTUMN WINTER |
Moreover, since we can traverse through each object by using this method, it is easy to call a method for each item like this;
Again, I use the main() method. But note that, I have added a few extra lines above the for-each loop.
1 2 3 4 5 6 7 8 9 10 11 12 |
public static void main(String[] args){ Seasons mySeason = Seasons.AUTUMN; mySeason.setSeasonDetails("this is a test!"); mySeason.getInfo(); System.out.println("///////////"); for(Seasons s:Seasons.values()){ s.getInfo(); } } |
Output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
This is the autumn. more information: this is a test! /////////// This is the spring. more information: None This is the summer. more information: None This is the autumn. more information: this is a test! This is the cold winter. more information: None |
Are Enum Constants Immutable?
I’ll give the answer at the end. First, the meaning of this question is, can’t we change the values of Enum constants? For example, can we add another Enum constant in addition to the 4 constants that we have created? Can’t we make 2 AUTUMN objects? Can we delete one object and add another one instead? Answer for all is, we can’t. Let’s see.
In the previous code I have used the line
1 |
System.out.println("///////////"); |
in order to make the output of for each loop distinguishable from the previous output. In the previous output, we have assigned the Enum object AUTUMN in to the variable mySeason and called the setSeasonDetails() method to add a detail to the mySeason variable. But look sharply. The same detail is printed for the AUTUMN in for-each loop as well. Why? We made the change to the mySeason object! So why it is printed? Shouldn’t we call mySeason.getInfo() instead of s.getInfo()? NO!! Enum objects are constants. They are created once and will NOT change. We cannot create new objects of Seasons so the existing 4 objects are the only available ones. See for yourself by modifying the main() method as follows:
1 2 3 4 5 6 7 8 9 |
public static void main(String[] args){ Seasons mySeason = Seasons.AUTUMN; mySeason.setSeasonDetails("this is a test!"); mySeason.getInfo(); Seasons mySeason2 = Seasons.AUTUMN; mySeason2.getInfo(); } |
Output:
1 2 3 4 5 6 7 |
This is the autumn. more information: this is a test! This is the autumn. more information: this is a test! |
We didn’t call the setSeasonDetails() method for mySeason2 variable. If a new AUTUMN object is created in here, the output for the mySeason2.getInfo() should be
1 2 3 |
This is the autumn. more information: None |
The same reference for the AUTUMN object is assigned to both mySeason and mySeason2. Similarly, same AUTUMN in mySeason and s of the for-each loop.
Once we create two Enum variables, if we assign the same enum constant to both, then, they refer to the same Object.
So the answer to the question whether enum constants are immutable is: YES! Partially it’s true.
What about state? Aren’t we changing it?
True. We can of course change the state of the enum constants.
State means the values that are stored in instance variables of the Enum constants. For example, seasonDetails variable available in all 4 Seasons objects is an instance variable. We have changed the value stored in AUTUMN object in the previous example. So we are ultimately changing the state of the Enum constant AUTUMN.
If enum constant objects are REALLY immutable, then why can we mutate the object?
Yes, you can change the state of the object. But you can’t change the object itself. Though your look changes when you change clothes, your inside don’t change. Right?
Can We Make Enum Constants Fully Immutable?
Sure. Just make all instance variables are immutable. Remove all the setter methods in your program. Declare all the member variables final.
1 |
private final String seasonDetails; |
Then we can make constructors to initialize this final String variable.
1 2 3 4 5 6 7 |
Seasons(){ seasonDetails = "None"; } Seasons(String details){ this.seasonDetails = details; } |
Now when we declare the enum constants, we can assign a value for the seasonDetails.
1 |
SPRING, SUMMER, AUTUMN("Test"), WINTER; |
This won’t change after that. So, our enum constants are now fully immutable!