Java Enums

Java Enums

Overview

In this article we will a look at enums in java as well as its features and how to use enums more effectively in java 8 and more. We will also look at how enums are useful in design patterns like Singleton pattern. 

Programming Language uses enums for representing group of named constants. For example, the 4 cardinal points named EAST, WEST, NORTH and SOUTH are 4 enumerators belongs to an enumerated type Direction. Some of other examples of enumerators are Suits, planets, shapes, colors etc.

Java 5 official release introduced the keyword enum. The enum class extends java.lang.Enum class and implements Serializable and Comparable interfaces. For the official documentation on their usage, please have a look at documentation

public abstract class Enum> extends Object implements Comparable, Serializable

When to use Enums?

Typically, enums are used when we know all possible values at compile time, such as planets in the solar system and so on.

private enum Planet {
	MERCURY,
	VENUS,
	EARTH,
	MARS
}

Using Enum types in Switch Statements:

Below is the example for usage of enums type in switch statement

enum Planet {
	MERCURY,
	VENUS,
	EARTH,
	MARS,
	JUPITER,
	SATURN,
	URANUS,
	NEPTUNE
}
public class SwitchEnums {
	public static void main(String[] args) {
		Planet p = Planet.EARTH;
		switch(p) {
			case MERCURY :
				System.out.println("This is Mercury Planet");
				break;
			case VENUS :
				System.out.println("This is Venus Planet");
				break;
			case EARTH :
				System.out.println("This is Earth Planet");
				break;
			case MARS :
				System.out.println("This is Mars Planet");
				break;
			case JUPITER :
				System.out.println("This is Jupiter Planet");
				break;
			case SATURN :
				System.out.println("This is Saturn Planet");
				break;
			case URANUS :
				System.out.println("This is Uranus Planet");
				break;
			case NEPTUNE :
				System.out.println("This is Neptune Planet");
				break;
		}
	}
}
Output: 
This is Earth Planet

Enum Class Constructor:

There is only one constructor in Enum which takes name and ordinal as parameters.

protected Enum(String name, int ordinal);

Enum Class Methods:

S NoMethod & Description
1.Protected Object clone() Enums can never be cloned. So this method throws CloneNotSupportedException.
2.int compareTo(E o) This method compares enum with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. Enum constants are only comparable to other enum constants of the same enum type. The natural order implemented by this method is the order in which the constants are declared.
3.boolean equals (Object other) This method compares enum with object of other type. Here if the object is null then run time exceptions will occur.
4.protected void finalize() Enum classes cannot have finalize methods.
5.Class<E> getDeclaringClass() This method returns the Class object corresponding to this enum constant’s enum type. Two enum constants e1 and e2 are of the same enum type if and only if e1.getDeclaringClass() == e2.getDeclaringClass()
6.int hashCode() This method returns the hash code of the enum constant.
7.String name () This method returns the name of this enum constant, exactly as declared in its enum declaration. Most programmers should use the toString() method in preference to this one, as the toString method may return a more user-friendly name. This method is designed primarily for use in specialized situations where correctness depends on getting the exact name.
8.Int ordinal () This method returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero).
9.String toString () This method returns the name of this enum constant, as contained in the declaration. This method may be overridden, though it typically isn’t necessary or desirable. An enum type should override this method when a more “programmer-friendly” string form exists.
10.static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) This method returns the enum constant of the specified enum type with the specified name. The name must match exactly an identifier used to declare an enum constant in this type.

Lets have a example that explains all methods of enum class

enum TechiJournal {
	ANGULAR,
	MICROSERVICES,
	JAVA
}
public class EnumMethods {
	public static void main(String[] args) {
		TechiJournal tj1,tj2,tj3;
		tj1 = TechiJournal.ANGULAR;
		tj2 = TechiJournal.MICROSERVICES;
		tj3 = TechiJournal.JAVA;
                // compateTo method
		if(tj1.compareTo(tj2) < 0) {
			System.out.println(tj2 + " started before " + tj1);
		}
                // equals method
		if(tj1.equals(tj2)) {
			System.out.println(tj1 + " is equal to " + tj2);
		} else {
			System.out.println("All topics are different");
		}
                // getDeclaredClass method	 
        System.out.println(TechiJournal.ANGULAR.getDeclaringClass());
                // hashCode method
		System.out.println("Enum variable is : " + TechiJournal.ANGULAR + " and hashcode is : " + TechiJournal.ANGULAR.hashCode());
                // name method
		System.out.println("Name is : " + TechiJournal.JAVA.name());
                // ordinal method
		System.out.println("Ordinal is : " + TechiJournal.JAVA.ordinal());
                // toString method
		System.out.println("toString returns : " + TechiJournal.JAVA.toString());
	}
}

Output :
MICROSERVICES started before ANGULAR
All topics are different
class com.techijournal.enums.TechiJournal
Enum variable is : ANGULAR and hashcode is : 905544614
Name is : JAVA
Ordinal is : 2
toString returns : JAVA

EnumMap

A specialized Map implementation for use with enum type keys.

All the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created. EnumMap is internally represented as arrays. This representation is extremely compact and efficient.

Enum maps elements are maintained in the natural order of their keys (the order in which the enum constants are declared). This is reflected in the iterators returned by the collections views (keySet(), entrySet(), and values()).

public class EnumMapExample {
	// create an enum
	public enum Days {
		Monday, Tuesday, Wednesday, Thursday
	};
	public static void main(String[] args) {
		// create and populate enum map
		EnumMap map = new EnumMap(Days.class);
		map.put(Days.Monday, "1");
		map.put(Days.Tuesday, "2");
		map.put(Days.Wednesday, "3");
		map.put(Days.Thursday, "4");
		// print the map
		for (Map.Entry m : map.entrySet()) {
			System.out.println(m.getKey() + " " + m.getValue());
		}
	}
}

Output:
Monday 1
Tuesday 2
Wednesday 3
Thursday 4

EnumSet

A specialized Set implementation for use with enum types. All of the elements in an enum set must come from a single enum type that is specified, explicitly or implicitly, when the set is created.

Enum sets are represented internally as bit vectors. This representation is extremely compact and efficient. The space and time performance of this class should be good enough to allow its use as a high-quality, type safe alternative to traditional int-based “bit flags.” Even bulk operations (such as containsAll and retainAll) should run very quickly if their argument is also an enum set.

Enum class returns iterator this can be used to traverses the elements in their natural order (the order in which the enum constants are declared). The returned iterator is weakly consistent: it will never throw ConcurrentModificationException and it may or may not show the effects of any modifications to the set that occur while the iteration is in progress.

enum days {
	SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
public class EnumSetExample {
	public static void main(String[] args) {
		Set set1 = EnumSet.allOf(days.class);
		System.out.println("Week Days:" + set1);
		Set set2 = EnumSet.noneOf(days.class);
		System.out.println("Week Days:" + set2);
		Iterator iter = set1.iterator();  
	    while (iter.hasNext())  
	      System.out.println(iter.next());    
	}
}

Output :
Week Days:[SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY]
Week Days:[]
SUNDAY  MONDAY  TUESDAY  WEDNESDAY  THURSDAY  FRIDAY  SATURDAY

Let’s have an example to find weight on all planets provides mass of each planet using enums

enum Planets {
	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
	Planets(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 ");
			System.exit(-1);
		}
		double earthWeight = Double.parseDouble(args[0]);
		double mass = earthWeight / EARTH.surfaceGravity();
		for (Planets p : Planets.values())
			System.out.printf("Your weight on %s is %f%n", p, p.surfaceWeight(mass));
	}
}

Output:
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

Design Patterns using Enums :

The three lines above make a singleton without any of the problems discussed. Since enums are inherently serializable, we don’t need to implement it with a serializable interface. The reflection problem is also not there. Therefore, it is 100% guaranteed that only one instance of the singleton is present within a JVM. Thus, this method is recommended as the best method of making singletons in Java.

public enum SingletonEnum {
    INSTANCE;
    int value;
    public int getValue() {
        return value;
    }
    public void setValue(int value) {
        this.value = value;
    }
}

Important Points:

  • The constructor for an enum type must be package or private access. There fore it automatically creates the constants that are defined at the beginning of the enum body. You cannot invoke an enum constructor yourself.
  • Enum declaration cannot be done inside a method. It can be done outside or inside classes.
  • Enums class should be started with constants. Then you can create variables, methods, static methods or etc.
  • Enum is internally implemented by Class.
    Example: class Shape { public static final Shape RECTANGLE = new Shape (); }
  • Since enum types ensure that only one instance of the constants exist in the JVM, we can safely use “==” operator to compare two variables as seen in the example above; moreover the “==” operator provides compile-time and run-time safety.
  • Every enum constant is always implicitly public static final. Since it is static, we can access it by using enum Name. Since Enum Class is final, we can’t create child enums.
  • We can declare main() method inside Enum.
  • The iterator of EnumSet and EnumMap will never throw ConcurrentModificationException and it may or may not show the effects of any modifications to the set that occur while the iteration is in progress.
  • EnumSet and EnumMap do not permit null elements. If we attempt to insert a null element it will throw NullPointerException. But the attempt to test for the presence of a null element or to remove one will function properly and wont throw any compile time or run time errors.
  • EnumSet and EnumMap are not synchronized. If multiple threads access an enum set and enum map concurrently, and at least one of the threads modifies the set or map, it should be synchronized externally.

Conclusion

An enumeration, short form of enum, is a Java data type that has a fixed set of values. Enums are useful if you are working with variables that should only be capable of storing one out of a select range of values. In this tutorial, we used the example of planets: when you mass of object on planets you should only be able to choose out of existing planets.

This tutorial discussed the basics of enums in Java. Additionally, we covered how to declare an enum and how to work with enums in Java code. This tutorial also explained how four of the main enum methods work, with reference to examples.

After practicing what you have read in this tutorial, you’ll be an expert at using enums in Java.

Thanks, Note

Thanks for spending your valuable time reading this post. Hope this post taught you something new today. Please share our post if you like it.

 

Sumanth Patnaikuni

Hi Guys. I am a technology enthusiast always try to learn new things. So I decided to share my knowledge through this platform. I worked for several companies and having 4+ years of experience. as full stack developer. Please leave your comments if there is any doubt regarding the blog. And also please recommend me if you require any particular topic so that I can guide you through my blog.

Leave a Reply