What's the use of "enum" in Java? [duplicate]
So I looked into this "enum" type, and it kind of seems like a glorified array/ArrayList
/List
to me. What exactly is the use of it?
Enum serves as a type of fixed number of constants and can be used at least for two things
constant
public enum Month {
JANUARY, FEBRUARY, ...
}
This is much better than creating a bunch of integer constants.
creating a singleton
public enum Singleton {
INSTANCE
// init
};
You can do quite interesting things with enums, look at here
Also look at the official documentation
You use an enum
instead of a class
if the class should have a fixed enumerable number of instances.
Examples:
-
DayOfWeek
= 7 instances →enum
-
CardSuit
= 4 instances →enum
-
Singleton
= 1 instance →enum
-
Product
= variable number of instances →class
-
User
= variable number of instances →class
-
Date
= variable number of instances →class
An enumerated type is basically a data type that lets you describe each member of a type in a more readable and reliable way.
Here is a simple example to explain why:
Assuming you are writing a method that has something to do with seasons:
The int enum pattern
First, you declared some int static constants to represent each season.
public static final int SPRING = 0;
public static final int SUMMER = 1;
public static final int FALL = 2;
public static final int WINTER = 2;
Then, you declared a method to print name of the season into the console.
public void printSeason(int seasonCode) {
String name = "";
if (seasonCode == SPRING) {
name = "Spring";
}
else if (seasonCode == SUMMER) {
name = "Summer";
}
else if (seasonCode == FALL) {
name = "Fall";
}
else if (seasonCode == WINTER) {
name = "Winter";
}
System.out.println("It is " + name + " now!");
}
So, after that, you can print a season name like this.
printSeason(SPRING);
printSeason(WINTER);
This is a pretty common (but bad) way to do different things for different types of members in a class. However, since these code involves integers, so you can also call the method like this without any problems.
printSeason(0);
printSeason(1);
or even like this
printSeason(x - y);
printSeason(10000);
The compiler will not complain because these method calls are valid, and your printSeason
method can still work.
But something is not right here. What does a season code of 10000
supposed to mean? What if x - y
results in a negative number? When your method receives an input that has no meaning and is not supposed to be there, your program knows nothing about it.
You can fix this problem, for example, by adding an additional check.
...
else if (seasonCode == WINTER) {
name = "Winter";
}
else {
throw new IllegalArgumentException();
}
System.out.println(name);
Now the program will throw a RunTimeException
when the season code is invalid. However, you still need to decide how you are going to handle the exception.
By the way, I am sure you noticed the code of FALL
and WINTER
are both 2, right?
You should get the idea now. This pattern is brittle. It makes you write condition checks everywhere. If you're making a game, and you want to add an extra season into your imaginary world, this pattern will make you go though all the methods that do things by season, and in most case you will forget some of them.
You might think class inheritance is a good idea for this case. But we just need some of them and no more.
That's when enum
comes into play.
Use enum
type
In Java, enum
types are classes that export one instance for each enumeration constant via a public static final field.
Here you can declare four enumeration constants: SPRING, SUMMER, FALL, WINTER
. Each has its own name
.
public enum Season {
SPRING("Spring"), SUMMER("Summer"), FALL("Fall"), WINTER("Winter");
private String name;
Season(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
Now, back to the method.
public void printSeason(Season season) {
System.out.println("It is " + season.getName() + " now!");
}
Instead of using int
, you can now use Season
as input. Instead of a condition check, you can tell Season
to give you its name.
This is how you use this method now:
printSeason(Season.SPRING);
printSeason(Season.WINTER);
printSeason(Season.WHATEVER); <-- compile error
You will get a compile-time error when you use an incorrect input, and you're guaranteed to get a non-null singleton reference of Season
as long as the program compiles.
When we need an additional season, we simply add another constant in Season
and no more.
public enum Season {
SPRING("Spring"), SUMMER("Summer"), FALL("Fall"), WINTER("Winter"),
MYSEASON("My Season");
...
Whenever you need a fixed set of constants, enum
can be a good choice (but not always). It's a more readable, more reliable and more powerful solution.
An enum type is a type whose fields consist of a fixed set of constants. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}
You should use enum types any time you need to represent a fixed set of constants. That includes natural enum types such as the planets in our solar system and data sets where you know all possible values at compile time—for example, the choices on a menu, command line flags, and so on.
Here is some code that shows you how to use the Day enum defined above:
public class EnumTest {
Day day;
public EnumTest(Day day) {
this.day = day;
}
public void tellItLikeItIs() {
switch (day) {
case MONDAY:
System.out.println("Mondays are bad.");
break;
case FRIDAY:
System.out.println("Fridays are better.");
break;
case SATURDAY: case SUNDAY:
System.out.println("Weekends are best.");
break;
default:
System.out.println("Midweek days are so-so.");
break;
}
}
public static void main(String[] args) {
EnumTest firstDay = new EnumTest(Day.MONDAY);
firstDay.tellItLikeItIs();
EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
thirdDay.tellItLikeItIs();
EnumTest fifthDay = new EnumTest(Day.FRIDAY);
fifthDay.tellItLikeItIs();
EnumTest sixthDay = new EnumTest(Day.SATURDAY);
sixthDay.tellItLikeItIs();
EnumTest seventhDay = new EnumTest(Day.SUNDAY);
seventhDay.tellItLikeItIs();
}
}
The output is:
Mondays are bad.
Midweek days are so-so.
Fridays are better.
Weekends are best.
Weekends are best.
Java programming language enum types are much more powerful than their counterparts in other languages. The enum declaration defines a class (called an enum type). The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared. This method is commonly used in combination with the for-each construct to iterate over the values of an enum type. For example, this code from the Planet class example below iterates over all the planets in the solar system.
for (Planet p : Planet.values()) {
System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}
In addition to its properties and constructor, Planet has methods that allow you to retrieve the surface gravity and weight of an object on each planet. Here is a sample program that takes your weight on earth (in any unit) and calculates and prints your weight on all of the planets (in the same unit):
public enum Planet {
MERCURY (3.303e+23, 2.4397e6),
VENUS (4.869e+24, 6.0518e6),
EARTH (5.976e+24, 6.37814e6),
MARS (6.421e+23, 3.3972e6),
JUPITER (1.9e+27, 7.1492e7),
SATURN (5.688e+26, 6.0268e7),
URANUS (8.686e+25, 2.5559e7),
NEPTUNE (1.024e+26, 2.4746e7);
private final double mass; // in kilograms
private final double radius; // in meters
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
private double mass() { return mass; }
private double radius() { return radius; }
// universal gravitational constant (m3 kg-1 s-2)
public static final double G = 6.67300E-11;
double surfaceGravity() {
return G * mass / (radius * radius);
}
double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: java Planet <earth_weight>");
System.exit(-1);
}
double earthWeight = Double.parseDouble(args[0]);
double mass = earthWeight/EARTH.surfaceGravity();
for (Planet p : Planet.values())
System.out.printf("Your weight on %s is %f%n",
p, p.surfaceWeight(mass));
}
}
If you run Planet.class from the command line with an argument of 175, you get this output:
$ java Planet 175
Your weight on MERCURY is 66.107583
Your weight on VENUS is 158.374842
Your weight on EARTH is 175.000000
Your weight on MARS is 66.279007
Your weight on JUPITER is 442.847567
Your weight on SATURN is 186.552719
Your weight on URANUS is 158.397260
Your weight on NEPTUNE is 199.207413
Source: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
an Enum is a safe-type so you can't assign a new value at the runtime. Moreover you can use it in a switch statement (like an int).