This text introduces you to the distinction between enumerated sorts and typesafe enums. You’ll learn to declare a typesafe enum and use it in a swap assertion, and you will see the right way to customise a typesafe enum by including information and behaviors. We’ll additionally check out java.lang.Enum<E extends Enum<E>>, which is the bottom class for all typesafe enums.
What you may study on this Java tutorial
- Why use typesafe enums and never enumerated sorts
- The best way to use typesafe enums in swap statements
- The best way to add information and behaviors to typesafe enums
- Particulars and examples of the Enum class (Enum<E extends Enum<E>>)
Why use typesafe enums, not enumerated sorts
An enumerated kind specifies a set of associated constants as its values. Examples embrace the times in every week, the usual north/south/east/west compass instructions, a forex’s coin denominations, and a lexical analyzer’s token sorts.
Enumerated sorts have historically been applied as sequences of integer constants, which is demonstrated by the next set of path constants:
static last int DIR_NORTH = 0;
static last int DIR_WEST = 1;
static last int DIR_EAST = 2;
static last int DIR_SOUTH = 3;
There are a number of issues with this strategy:
- It lacks kind security: As a result of an enumerated kind fixed is simply an integer, any integer might be specified the place the fixed is required. Moreover, addition, subtraction, and different math operations might be carried out on these constants; for instance,
(DIR_NORTH + DIR_EAST) / DIR_SOUTH), which is meaningless. - The namespace is not current: An enumerated kind’s constants have to be prefixed with some sort of (hopefully) distinctive identifier (e.g.,
DIR_) to forestall collisions with one other enumerated kind’s constants. - The code is brittle: As a result of enumerated kind constants are compiled into class recordsdata the place their literal values are saved (in fixed swimming pools), altering a continuing’s worth requires that these class recordsdata and people software class recordsdata that rely upon them be rebuilt. In any other case, undefined conduct will happen at runtime.
- Not sufficient data: When a continuing is printed, its integer worth outputs. This output tells you nothing about what the integer worth represents. It doesn’t even establish the enumerated kind to which the fixed belongs.
You possibly can keep away from the “lack of kind security” and “not sufficient data” issues by utilizing java.lang.String constants. For instance, you may specify static last String DIR_NORTH = "NORTH";. Though the fixed worth is extra significant, String-based constants nonetheless undergo from “namespace not current” and brittleness issues. Additionally, not like integer comparisons, you can not examine string values with the == and != operators (which solely examine references).
To resolve these issues, builders invented a class-based various often called typesafe enum. Sadly, this sample had quite a few challenges. I am going to present an instance that summarizes the problems.
Challenges of the typesafe enum sample
The Swimsuit class reveals the way you may use the typesafe enum sample to introduce an enumerated kind describing the 4 card fits:
public last class Swimsuit // Shouldn't be capable of subclass Swimsuit.
{
public static last Swimsuit CLUBS = new Swimsuit();
public static last Swimsuit DIAMONDS = new Swimsuit();
public static last Swimsuit HEARTS = new Swimsuit();
public static last Swimsuit SPADES = new Swimsuit();
non-public Swimsuit() {} // Shouldn't be capable of introduce extra constants.
}
To make use of this class, you’d introduce a Swimsuit variable and assign it to one among Swimsuit’s constants:
Swimsuit swimsuit = Swimsuit.DIAMONDS;
You may then need to interrogate swimsuit in a swap assertion like this one:
swap (swimsuit)
{
case Swimsuit.CLUBS : System.out.println("golf equipment"); break;
case Swimsuit.DIAMONDS: System.out.println("diamonds"); break;
case Swimsuit.HEARTS : System.out.println("hearts"); break;
case Swimsuit.SPADES : System.out.println("spades");
}
Nevertheless, when the Java compiler encounters Swimsuit.CLUBS, it reviews an error stating {that a} fixed expression is required. You may attempt to tackle the issue as follows:
swap (swimsuit)
{
case CLUBS : System.out.println("golf equipment"); break;
case DIAMONDS: System.out.println("diamonds"); break;
case HEARTS : System.out.println("hearts"); break;
case SPADES : System.out.println("spades");
}
However when the compiler encounters CLUBS, it is going to report an error stating that it was unable to seek out the image. And even when you positioned Swimsuit in a package deal, imported the package deal, and statically imported these constants, the compiler would complain that it can not convert Swimsuit to int when encountering swimsuit in swap(swimsuit). Relating to every case, the compiler would additionally report {that a} fixed expression is required.
Java doesn’t assist the typesafe enum sample with swap statements. Nevertheless, you should use the typesafe enum language characteristic, which encapsulates the sample’s advantages whereas resolving its points. This characteristic additionally helps swap.
The best way to use typesafe enums in swap statements
A easy typesafe enum declaration in Java code seems like its counterparts within the C, C++, and C# languages:
enum Course { NORTH, WEST, EAST, SOUTH }
This declaration makes use of the key phrase enum to introduce Course as a typesafe enum (a particular sort of class), by which arbitrary strategies might be added and arbitrary interfaces might be applied. The NORTH, WEST, EAST, and SOUTH enum constants are applied as constant-specific class our bodies that outline nameless lessons extending the enclosing Course class.
Course and different typesafe enums lengthen Enum<E extends Enum<E>> and inherit numerous strategies, together with values(), toString(), and compareTo(), from this class. We’ll discover Enum later on this article.
Itemizing 1 declares the aforementioned enum and makes use of it in a swap assertion. It additionally reveals the right way to examine two enum constants, to find out which fixed comes earlier than the opposite fixed.
Itemizing 1. TEDemo.java (model 1)
public class TEDemo
{
enum Course { NORTH, WEST, EAST, SOUTH }
public static void most important(String[] args)
{
for (int i = 0; i < Course.values().size; i++)
{
Course d = Course.values()[i];
System.out.println(d);
swap (d)
{
case NORTH: System.out.println("Transfer north"); break;
case WEST : System.out.println("Transfer west"); break;
case EAST : System.out.println("Transfer east"); break;
case SOUTH: System.out.println("Transfer south"); break;
default : assert false: "unknown path";
}
}
System.out.println(Course.NORTH.compareTo(Course.SOUTH));
}
}
Itemizing 1 declares the Course typesafe enum and iterates over its fixed members, which values() returns. For every worth, the swap assertion (enhanced to assist typesafe enums) chooses the case that corresponds to the worth of d and outputs an applicable message. (You don’t prefix an enum fixed, e.g., NORTH, with its enum kind.) Lastly, Itemizing 1 evaluates Course.NORTH.compareTo(Course.SOUTH) to find out if NORTH comes earlier than SOUTH.
Compile the supply code as follows:
javac TEDemo.java
Run the compiled software as follows:
java TEDemo
You must observe the next output:
NORTH
Transfer north
WEST
Transfer west
EAST
Transfer east
SOUTH
Transfer south
-3
The output reveals that the inherited toString() technique returns the title of the enum fixed, and that NORTH comes earlier than SOUTH in a comparability of those enum constants.
The best way to add information and behaviors in typesafe enums
You’ll be able to add information (within the type of fields) and behaviors (within the type of strategies) to a typesafe enum. For instance, suppose it is advisable introduce an enum for Canadian cash, and also you need the category to supply the means to return the variety of nickels, dimes, quarters, or {dollars} contained in an arbitrary variety of pennies. Itemizing 2 reveals you the right way to accomplish this process.
Itemizing 2. TEDemo.java (model 2)
enum Coin
{
NICKEL(5), // constants should seem first
DIME(10),
QUARTER(25),
DOLLAR(100); // the semicolon is required
non-public last int valueInPennies;
Coin(int valueInPennies)
{
this.valueInPennies = valueInPennies;
}
int toCoins(int pennies)
{
return pennies / valueInPennies;
}
}
public class TEDemo
{
public static void most important(String[] args)
{
if (args.size != 1)
{
System.err.println("utilization: java TEDemo amountInPennies");
return;
}
int pennies = Integer.parseInt(args[0]);
for (int i = 0; i < Coin.values().size; i++)
System.out.println(pennies + " pennies comprises " +
Coin.values()[i].toCoins(pennies) + " " +
Coin.values()[i].toString().toLowerCase() + "s");
}
}
Itemizing 2 first declares a Coin enum. An inventory of parameterized constants identifies 4 sorts of cash. The argument handed to every fixed represents the variety of pennies that the coin represents.
The argument handed to every fixed is handed to the Coin(int valueInPennies) constructor, which saves the argument within the valuesInPennies occasion area. This variable is accessed from inside the toCoins() occasion technique. It divides into the variety of pennies handed to toCoin()’s pennies parameter, and this technique returns the outcome, which occurs to be the variety of cash within the financial denomination described by the Coin fixed.
At this level, you’ve found you could declare occasion fields, constructors, and occasion strategies in a typesafe enum. In any case, a typesafe enum is actually a particular sort of Java class.
The TEDemo class’s most important() technique first verifies {that a} single command-line argument has been specified. This argument is transformed to an integer by calling the java.lang.Integer class’s parseInt() technique, which parses the worth of its string argument into an integer (or throws an exception when invalid enter is detected).
Transferring ahead, most important() iterates over Coin’s constants. As a result of these constants are saved in a Coin[] array, most important() evaluates Coin.values().size to find out the size of this array. For every iteration of loop index i, most important() evaluates Coin.values()[i] to entry the Coin fixed. It invokes every of toCoins() and toString() on this fixed, which additional proves that Coin is a particular sort of class.
Compile the supply code as follows:
javac TEDemo.java
Run the compiled software as follows:
java TEDemo 198
You must observe the next output:
198 pennies comprises 39 nickels
198 pennies comprises 19 dimes
198 pennies comprises 7 quarters
198 pennies comprises 1 {dollars}
What it is advisable find out about Enum (Enum<E extends Enum<E>>)
The Java compiler considers enum to be syntactic sugar. Upon encountering a typesafe enum declaration, it generates a category whose title is specified by the declaration. This class subclasses the summary Enum<E extends Enum<E>> class, which serves as the bottom class for all typesafe enums.
Enum’s formal kind parameter checklist seems ghastly, however it’s not that onerous to grasp. For instance, within the context of Coin extends Enum<Coin>, you’d interpret this formal kind parameter checklist as follows:
- Any subclass of
Enumshould provide an precise kind argument toEnum. For instance,Coin’s header specifiesEnum<Coin>. - The precise kind argument have to be a subclass of
Enum. For instance,Coinis a subclass ofEnum. - A subclass of
Enum(equivalent toCoin) should comply with the idiom that it provides its personal title (Coin) as an precise kind argument.
Study Enum’s Java documentation and also you’ll uncover that it overrides java.lang.Object‘s clone(), equals(), finalize(), hashCode(), and toString() strategies. Apart from toString(), all of those overriding strategies are declared last in order that they can’t be overridden in a subclass:
clone()is overridden to forestall constants from being cloned so that there’s by no means a couple of copy of a continuing; in any other case, constants couldn’t be in contrast through==and!=.equals()is overridden to match constants through their references. Constants with the identical identities (==) will need to have the identical contents (equals()), and completely different identities suggest completely different contents.finalize()is overridden to make sure that constants can’t be finalized.hashCode()is overridden as a result ofequals()is overridden.toString()is overridden to return the fixed’s title.
Enum additionally offers its personal strategies. These strategies embrace the last compareTo() (Enum implements the java.lang.Comparable<T> interface), getDeclaringClass(), title(), and ordinal() strategies:


