This article detailed the concepts, principles, and case demonstrations of enumerations in Java, such as custom enumerations.

@[TOC]

1 the enumeration

Enumeration refers to listing the values of a variable one by one. The values of a variable are limited to the range of listed values. Examples: there are only 7 days in a week, 12 months in a year, etc.

Recall the singleton design pattern: a singleton class is a class with only one instance.

That’s a class that has multiple instances, not an infinite number of instances, but a finite number of instances, which is also called an enumerated class.

1.1 features

Enum has the same status as class and interface. Can inherit multiple interfaces; You can have constructors, member methods, member variables;

Enumeration classes differ from normal classes:

  1. The java.lang.Enum class is inherited by default, so no other parent class can be inherited; The java.lang.Enum class implements java.lang.Serializable and java.lang.Comparable interfaces.
  2. It is defined using enum and final is used by default, so it cannot be subclassed.
  3. Constructors use private decorations by default and only private decorations;
  4. All instances of the enumerated class must be given in the first line, and the public static final modifier is added by default, otherwise the instance cannot be generated.

Traditional custom enumerated classes

2.1 the first

public class Direction {
    public static final Direction FRONT = new Direction();
    public static final Direction BEHIND = new Direction();
    public static final Direction LEFT = new Direction();
    public static final Direction RIGHT = new Direction();
​
    private Direction() {
    }
}
Copy the code

2.2 the second

public class Direction2 { public static final Direction2 FRONT = new Direction2(); Public static final Direction2 BEHIND = new Direction2; Public static final Direction2 LEFT = new Direction2(" LEFT "); Public static final Direction2 RIGHT = new Direction2(" RIGHT "); Private Direction2() {} /** * add a member variable */ private String name; /** @param */ private Direction2(String name) {this.name = name; } /** * public String getName() {return name; }}Copy the code

2.3 the third

Public class Direction3 {public static final Direction3 FRONT = new Direction3(" FRONT ") {@override public void Show () {system.out.println (" I am the front "); }}; Public static final Direction3 BEHIND = new Direction3(" ") {@override public void show() {system.out.println (" ");  }}; Public static final Direction3 LEFT = new Direction3(" LEFT ") {@override public void show() {system.out.println (" LEFT "); }}; Public static final Direction3 RIGHT = new Direction3(" RIGHT ") {@override public void show() {system.out.println (" I am RIGHT "); }}; /** * add an abstract method. When defining enumerations, you must implement */ public abstract void show(); private String name; private Direction3(String name) { this.name = name; } public String getName() { return name; }}Copy the code

2.4 test

/** * public class DirectionTest {/** * public void test1() {Direction sbehind = Direction.BEHIND; } @test public void test2() {// Test 2 Direction2 behind = direction2.behind; / / System. After the out. Println (behind. The getName ()); } @test public void test3() {// Test 3 Direction3 = direction3.front; System.out.println(d2.getName()); d2.show(); }}Copy the code

3 Enumeration classes provided by the JDK

We found it cumbersome to define an enumeration class ourselves, so JDK1.5 provided enumeration classes for us to use from the start.

The format is: enumeration class with only enumeration items

Public enum Enumeration class name {Enumeration item 1, Enumeration item 2, Enumeration item 3… ; }

3.1 the first

Public enum DirectionEnum1 {/** * public static final */ FRONT, BEHIND, LEFT, RIGHT}Copy the code

3.2 the second

Public enum DirectionEnum2 {/** * public static final */ FRONT(" FRONT "), BEHIND(" LEFT "), LEFT(" LEFT "), LEFT(" LEFT ") RIGHT (" RIGHT "); /** * can have arguments */ private String name; /** @param name */ DirectionEnum2(String name) {this.name = name; } /** * public String getName() {return name; }}Copy the code

3.3 the third

Public enum DirectionEnumeration {/** * public static final {/** * public static final {/** * public static final {/** * public static final { @override public void show() {system.out.println (); }}, @override public void show() {system.out.println (" BEHIND "); }}, @override public void show() {system.out.println (" LEFT "); }}, RIGHT(" RIGHT ") {@override public void show() {system.out.println (); }}; private String name; /** @param name */ DirectionEnum3(String name) {this.name = name; } public String getName() { return name; } /** * can have abstract methods */ public void show(); }Copy the code

3.4 test

/** * Test enum Enum1 */ @test public void test4() {// Test enum1 DirectionEnum1 front = DirectionEnum1. Front; } /** * Test enum Enum2 */ @test public void test5() {// Test enum2 DirectionEnum2 front = DirectionEnum2. Front; System.out.println(front.getName()); } /** * Test enum Enum3 */ @test public void test6() {// Test enum3 DirectionEnum3 front = DirectionEnum3. Front; System.out.println(front.getName()); front.show(); }Copy the code

4 Precautions

  1. The keyword enum is used to define enumerated classes
  2. All enumerated classes are subclasses of Enum
  3. The first line of an enumeration must be an enumeration item. The semicolon after the last enumeration item may be omitted, but not if the enumeration class has something else. Do not omit
  4. Enumerated classes can have parameter constructors, but they must be private, as they are by default, and the use of parameter enumerators is special: enumerators (arguments);
  5. Enumeration classes can also have abstract methods, but the enumeration item must override that method
  6. The use of enumeration in switch statements (after JDk1.5) is illustrated below.
  7. The equals method does not have to be used to compare values between objects of enumeration type directly, using ==. Because the Enum class Enum overrides equals
public final boolean equals(Object other) {
    return this==other;
}
Copy the code

4.1 Enumeration in Switch

Only byte, short, char, and int can be detected before Switch. Enum enum is supported after JDK1.5. Judging String is supported after jdk1.7.

Place enumeration options directly after Case rather than by class name. The call.

@Test public void test7() { DirectionEnum1 de = DirectionEnum1.BEHIND; // de = DirectionEnum1.FRONT; Switch (de) {case FRONT: system.out.println (" you chose the FRONT "); break; Case BEHIND: system.out.println (" select "); case BEHIND: system.out.println (" select "); break; Case LEFT: system.out.println (" select LEFT "); break; Case RIGHT: system.out.println (" you chose RIGHT "); break; default: } }Copy the code

5 Enum Common API methods

public abstract class Enum<E extends Enum> extends Object implements Comparable, Serializable

Located in the java.lang.Enum package, JDK1.4. Is the common base class for all Java language enumerated types.

5.1 public final int compareTo(E o)

Compares the order of this enumeration with the specified objects. Returns a negative integer, zero, or positive integer when the object is less than, equal to, or greater than the specified object. Enumeration constants can only be compared to other enumeration constants of the same enumeration type. The natural order in which this method is implemented is the order in which constants are declared.

Example: The following enumerations are declared in the order FRONT, BEHIND, LEFT, RIGHT

public class EnumApi { @Test public void test1() { DirectionEnum1 front = DirectionEnum1.FRONT; DirectionEnum1 behind = DirectionEnum1.BEHIND; DirectionEnum1 left = DirectionEnum1.LEFT; DirectionEnum1 right = DirectionEnum1.RIGHT; System.out.println(front.compareTo(front)); //0 System.out.println(behind.compareTo(front)); //1 System.out.println(left.compareTo(front)); //2 System.out.println(right.compareTo(front)); //3 System.out.println(behind.compareTo(right)); / / - 2}}Copy the code

5.2 Public Final String Name ()

Returns the name of this enumeration constant to declare in its enumeration declaration. Most programmers should give preference to the toString() method over this one, because the toString method returns a more user-friendly name. This method is designed primarily for special cases, and its correctness depends on getting the right name, which does not change from version to version.

System.out.println(front.name());  //FRONT
System.out.println(behind.name());  //BEHIND
System.out.println(left.name());  //LEFT
System.out.println(right.name());  //RIGHT
Copy the code

5.3 Other Methods

public final int ordinal()

Returns the ordinal of the enumeration constant (its position in the enumeration declaration, where the initial constant ordinal is zero). Most programmers don’t use this approach. It is designed to work with complex enumeration-based data structures such as EnumSet and EnumMap.

The constant Ordinal Numbers of the above enumeration are :0,1,2,3

public String toString()

Returns the name of the enumeration constant contained in the declaration. You can override this method.

public static <T extends Enum> T valueOf(Class enumType, String name)

Returns an enumeration constant of the specified enumeration type with the specified name. The name must exactly match the identifier used to declare enumeration constants in this type. (Additional whitespace characters are not allowed.)

DirectionEnum2 behind1 = DirectionEnum2.valueOf(DirectionEnum2.class, "BEHIND"); System.out.println(behind1.getName()); / / afterCopy the code

static values()

This method is not found in the JDK documentation, but it is present in every enumerated class, and it is very convenient to iterate over all the enumeration values of an enumerated class. This method is added to the virtual machine during compilation.

DirectionEnum2[] values = DirectionEnum2.values(); for (DirectionEnum2 value : values) { System.out.print(value.getName()); // front back left right}Copy the code

6 Principle of enumeration

Enumerations are essentially implemented by ordinary classes, but the compiler handles them for us. Each enumerated type inherits from java.lang.Enum and automatically adds values and valueOf methods.

Each enumerated constant is a static constant field, implemented using an inner class that inherits from the enumerated class. All enumerated constants are initialized by static code blocks, that is, during class loading.

In addition, clone, readObject and writeObject methods are defined as final in the inherited Enum class, and corresponding exceptions are thrown at the same time. This ensures that each enumeration type and enumeration constant is immutable. These two features of enumeration can be leveraged to implement thread-safe singletons.

Decompiled enumerated classes:

public final class DirectionEnum1 extends Enum { public static final DirectionEnum1 FRONT; public static final DirectionEnum1 BEHIND; public static final DirectionEnum1 LEFT; public static final DirectionEnum1 RIGHT; private static final DirectionEnum1 $VALUES[]; public static DirectionEnum1[] values() { return (DirectionEnum1[])$VALUES.clone(); } public static DirectionEnum1 valueOf(String name) { return (DirectionEnum1)Enum.valueOf(com/ikang/enumm/DirectionEnum1, name); } private DirectionEnum1(String s, int i) { super(s, i); } static { FRONT = new DirectionEnum1("FRONT", 0); BEHIND = new DirectionEnum1("BEHIND", 1); LEFT = new DirectionEnum1("LEFT", 2); RIGHT = new DirectionEnum1("RIGHT", 3); $VALUES = (new DirectionEnum1[] { FRONT, BEHIND, LEFT, RIGHT }); }}Copy the code

Methods of the inherited Enum class

/** * prevents deserialization, which requires writeObject() of ObjectOutputStream to convert the object to a byte stream and output it. The writeObject() method will reflect the writeObject() of the passed object if it has writeObject() to achieve serialization. Deserialization uses ObjectInputStream's readObject() method, which works similarly. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new InvalidObjectException("can't deserialize enum"); } private void readObjectNoData() throws ObjectStreamException { throw new InvalidObjectException("can't deserialize enum"); } / / protected to prevent cloning final Object clone () throws CloneNotSupportedException {throw new CloneNotSupportedException (); }Copy the code