preface

Happy New Year to you all as the Spring Festival approaches. Sorted out the Java enumeration related knowledge, is more basic, I hope we learn progress together.

All code demos in this chapter have been uploaded to Github

What is an enumeration type?

JDK5 introduces a new feature. The keyword enum can create a new type from a limited set of named values that can be used as regular program components.

A simple example of an enumeration

enum SeasonEnum {
    SPRING,SUMMER,FALL,WINTER;
}
Copy the code

Common methods for enumerating classes

Enum Common methods are as follows:

  • name(); Mandatory enum Instance name.
  • ordinal(); Returns an int representing the order in which enum instances are declared.
  • equals(); Returns a Boolean value, enum Instance equality
  • CompareTo () compares the order of enum instances with specified objects
  • values(); Mandatory enum Array of instances
  • ValueOf (String Name) Gets a constant defined in an enumeration class by name

Let’s get straight to the example:

enum Shrubbery { GROUND,CRAWLING, HANGING} public class EnumClassTest {public static void main(String[] args) {// VALUES Mandatory enum Array of instancesfor(Shrubbery Temp: shrubbery.values ()) {// NAME Mandatory Instance enum Declared name System.out.println(temp.name() +" ordinal is " + temp.ordinal() + " ,equal result is " +
                    Shrubbery.CRAWLING.equals(temp) + ",compare result is "+ Shrubbery.CRAWLING.compareTo(temp)); System.out.println(shrubbery.valueof ()); // Get the constant value defined in the enumeration class by name."CRAWLING")); }}Copy the code

Running results:

GROUND ordinal is 0 ,equal result is false,compare result is 1
CRAWLING ordinal is 1 ,equal result is true,compare result is 0
HANGING ordinal is 2 ,equal result is false,compare result is -1
CRAWLING
Copy the code

Enumerators

What exactly are enumerated types? Let’s create a simple enumeration to see what it looks like. As follows:

public enum Shrubbery {
    GROUND,CRAWLING, HANGING
}
Copy the code

Compile the above enumerated classes using Javac, resulting in the Shrubbery. Class file.

javac Shrubbery.java
Copy the code

Then use javap command, decompile to get the bytecode file. For example, run javap Shrubbery. Class to obtain the following bytecode files.

Compiled from "Shrubbery.java"
public final class enumtest.Shrubbery extends java.lang.Enum<enumtest.Shrubbery> {
  public static final enumtest.Shrubbery GROUND;
  public static final enumtest.Shrubbery CRAWLING;
  public static final enumtest.Shrubbery HANGING;
  public static enumtest.Shrubbery[] values();
  public static enumtest.Shrubbery valueOf(java.lang.String);
  static {};
}
Copy the code

From the bytecode file you can see:

  • The Shrubbery enumeration becomes a final modified class, that is, it cannot be inherited.
  • Shrubbery is a subclass of java.lang.Enum.
  • Shrubbery defines enumerations that are public static final.

For a closer look, javap decompiles with multiple arguments -c and executes the following command:

javap -c Shrubbery.class
Copy the code

The bytecode file for the static code block is as follows:

  static {};
    Code:
       0: new           #4 // class enumtest/Shrubbery
       3: dup
       4: ldc           #7 // String GROUND
       6: iconst_0
       7: invokespecial #8 // Method "
      
       ":(Ljava/lang/String; I)V
      
      10: putstatic     #9 // Field GROUND:Lenumtest/Shrubbery;
      13: new           #4 // class enumtest/Shrubbery
      16: dup
      17: ldc           #10 // String CRAWLING
      19: iconst_1
      20: invokespecial #8 // Method "
      
       ":(Ljava/lang/String; I)V
      
      23: putstatic     #11 // Field CRAWLING:Lenumtest/Shrubbery;
      26: new           #4 // class enumtest/Shrubbery
      29: dup
      30: ldc           #12 // String HANGING
      32: iconst_2
      33: invokespecial #8 // Method "
      
       ":(Ljava/lang/String; I)V
      
      36: putstatic     #13 // Field HANGING:Lenumtest/Shrubbery;
      39: iconst_3
      40: anewarray     #4 // class enumtest/Shrubbery
      43: dup
      44: iconst_0
      45: getstatic     #9 // Field GROUND:Lenumtest/Shrubbery;
      48: aastore
      49: dup
      50: iconst_1
      51: getstatic     #11 // Field CRAWLING:Lenumtest/Shrubbery;
      54: aastore
      55: dup
      56: iconst_2
      57: getstatic     #13 // Field HANGING:Lenumtest/Shrubbery;
      60: aastore
      61: putstatic     #1 // Field $VALUES:[Lenumtest/Shrubbery;
      64: return
}
Copy the code
  • Lines 0-39 instantiate the Shrubbery enumeration classes’ GROUND,CRAWLING, HANGING;
  • 40-64 Creates the Shrubbery[] array $VALUES and places the above three instantiated objects in the array.
  • Therefore, the enumeration class method values() returns an enum array of enumerated instances.

Fourth, the advantages of enumerated classes

What are the advantages of enumerated classes? Why did we choose to use enumerated classes? Because it makes code more readable, more maintainable, and more secure.

Enumerated classes enhance readability and maintainability

Suppose you have a business scenario where, after an order is completed, the buyer is notified to comment. It is easy to have the following code:

// Order completedif(3==orderStatus){
//do something    
}
Copy the code

Apparently, this code has magic numbers, and if you don’t comment it, who knows what status 3 represents, which is not only difficult to read, but also a pain to maintain? How about using an enumeration class, as follows:

public enum OrderStatusEnum {
    UNPAID(0, "Unpaid"), PAID(1, "Paid"), SEND(2, "Shipped"), FINISH(3, "Done"),;

    private int index;

    private String desc;

    public int getIndex() {
        return index;
    }

    public String getDesc() {
        returndesc; } OrderStatusEnum(int index, String desc) { this.index = index; this.desc = desc; }} // Order completedif(OrderStatusEnum.FINISH.getIndex()==orderStatus){
  //do something
 }
Copy the code

As you can see, enumerations make this code more readable and easier to maintain. Add a new order state, just add one more enumeration state. Public static final int public static final int public static final int

New Jersey = New Jersey; New Jersey = New Jersey; New Jersey = New Jersey; public static final int PAID = 1; public static final int SENDED = 2; public static final int FINISH = 3; } // Order completedif(OrderStatus.FINISH==orderStatus){
     //do something
 }
Copy the code

Of course, there is no problem with readability when static constants are implemented, and there is nothing wrong with writing code this way in everyday life. However, if you define a variable with the same int value, it will be confusing. If you define both PAID and SENDED states as 2, the compiler will not report an error.

Therefore, the first advantage of enumerated classes is readability and maintainability, so it is recommended.

Enumeration class security

In addition to readability and maintainability, enumerated classes have the great advantage of being secure.

From the enumeration class bytecode analysis in the previous section, we know:

  • An enumerated class is decorated with the final keyword and cannot be inherited.
  • And its variables are public static final, are static variables.

Static resources are initialized, Java classes are loaded, and the initialization process is thread-safe when a Java class is actually used for the first time.

Common uses of enumerations

Enum Organization constant

Before JDK5, constant definitions used to be like this: first define a class or interface, and the property type is public static final… Once you have enumerations, you can organize constants into enumerated classes as follows:

enum SeasonEnum {
    SPRING,SUMMER,FALL,WINTER,;
}
Copy the code

Enum and Switch are interlinked

In general, only integer values can be used in switch-case, but enumeration instances naturally have an order of integer values. Therefore, enums can be used in switch statements, as follows:

enum OrderStatusEnum {
   UNPAID, PAID, SEND, FINISH
}
public class OrderStatusTest {
    public static void main(String[] args) {
        changeByOrderStatus(OrderStatusEnum.FINISH);
    }

    static void changeByOrderStatus(OrderStatusEnum orderStatusEnum) {
        switch (orderStatusEnum) {
            case UNPAID:
                System.out.println("Boss, you placed your order. Pay now.");
                break;
            case PAID:
                System.out.println("I already paid for it.");
                break;
            case SENDED:
                System.out.println("Shipped");
                break;
            case FINISH:
                System.out.println("Order fulfilled.");
                break; }}}Copy the code

In daily development, enum is used with switch to make your code more readable.

Add a new method to the enumeration

You can add new methods to an enumeration class, such as get methods, ordinary methods, etc.

public enum OrderStatusEnum {
    UNPAID(0, "Unpaid"), PAID(1, "Paid"), SENDED(2, "Shipped"), FINISH(3, "Done"),; Private int index; private String desc; //get method public intgetIndex() {
        return index;
    }

    public String getDesc() {
        returndesc; } // Constructor method OrderStatusEnum(int index, String desc) {this.index = index; this.desc = desc; } public static OrderStatusEnum of(int index){for (OrderStatusEnum temp : values()) {
            if (temp.getIndex() == index) {
                returntemp; }}returnnull; }}Copy the code

Enumeration implementation interface

All enumerated classes inherit from java.lang.Enum, so enumerations can no longer inherit from other classes. But enumerations can implement interfaces, which adds color to enumerations. As follows:

public interface ISeasonBehaviour {

    void showSeasonBeauty();

    String getSeasonName();
}

public enum SeasonEnum implements ISeasonBehaviour {
    SPRING(1,"Spring"),SUMMER(2,"Summer"),FALL(3,"Autumn"),WINTER(4,"Winter"),; private int index; private String name; SeasonEnum(int index, String name) { this.index = index; this.name = name; } public intgetIndex() {
        return index;
    }
    public String getName() {
        returnname; } // Override public voidshowSeasonBeauty() {
        System.out.println("welcome to "+ this.name); } // Override public StringgetSeasonName() {
        returnthis.name; }}Copy the code

Use interfaces to organize enumerations

public interface Food {
    enum Coffee implements Food{  
        BLACK_COFFEE,DECAF_COFFEE,LATTE,CAPPUCCINO  
    }  
    enum Dessert implements Food{  
        FRUIT, CAKE, GELATO  
    }  
}
Copy the code

== = equals == =

Here’s an example:

public class EnumTest {
    public static void main(String[] args) {

        Shrubbery s1 = Shrubbery.CRAWLING;
        Shrubbery s2 = Shrubbery.GROUND;
        Shrubbery s3 = Shrubbery.CRAWLING;

        System.out.println("s1==s2,result: " + (s1 == s2));
        System.out.println("s1==s3,result: " + (s1 == s3));
        System.out.println("Shrubbery. CRAWLING. Equals (s1), the result:"+Shrubbery.CRAWLING.equals(s1));
        System.out.println("Shrubbery.CRAWLING.equals(s2),result: "+Shrubbery.CRAWLING.equals(s2)); }}Copy the code

Running results:

s1==s2,result: false
s1==s3,result: trueShrubbery. CRAWLING. Equals (s1), the result:true
Shrubbery.CRAWLING.equals(s2),result: false
Copy the code

You can see that it doesn’t matter whether you use == or equals. Actually the enumeration equals method, is to use the = = comparison, as follows:

public final boolean equals(Object other) {
    return this==other;
}
Copy the code

Enumeration of implementation singletons

Effective Java mentioned that the best singleton implementation pattern is the enumeration pattern. There are several ways to implement the singleton pattern. Why is enumeration the best?

Because singletons implemented by enumeration have the following advantages:

  • Enumeration singletons are simple to write
  • Enumerations solve thread-safety problems
  • Enumerations solve the problem of deserialization breaking singletons

An enumeration singleton demo looks like this:

public class SingletonEnumTest {
   public enum SingletonEnum {
        INSTANCE,;
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static void main(String[] args) {
        SingletonEnum.INSTANCE.setName("jay@huaxiao"); System.out.println(SingletonEnum.INSTANCE.getName()); }}Copy the code

There is about enumeration implementation singleton, want to in-depth understanding of the friends can see Hollis god this article, written really good! Why do I recommend using enumerations to implement singletons?

EnumSet and EnumMap

EnumSet

Let’s start with EnumSet’s inheritance diagram

Obviously, EnumSet also implements the set interface, which has the following advantages over HashSet:

  • Consumes less memory
  • It’s more efficient because it’s a bit vector implementation.
  • Predictable traversal order (declaration order of enum constants)
  • Refuse to add null

EnumSet is a high performance implementation of set. The requirement is to store the same enumeration type. Common methods of enumsetting:

  • Allof () creates an EnumSet containing all the enumeration values in the specified enumeration class
  • Range () gets an enumeration instance of a range
  • Of () creates an EnumSet containing all the enumeration elements in the argument
  • The initial enumeration of () includes the complementOf the specified enumeration set

Look at the examples, the most practical:

public class EnumTest {
    public static void main(String[] args) {
        // Creating a set
        EnumSet<SeasonEnum> set1, set2, set3, set4;

        // Adding elements
        set1 = EnumSet.of(SeasonEnum.SPRING,  SeasonEnum.FALL, SeasonEnum.WINTER);
        set2 = EnumSet.complementOf(set1);
        set3 = EnumSet.allOf(SeasonEnum.class);
        set4 = EnumSet.range(SeasonEnum.SUMMER,SeasonEnum.WINTER);
        System.out.println("Set 1: " + set1);
        System.out.println("Set 2: " + set2);
        System.out.println("Set 3: " + set3);
        System.out.println("Set 4: " + set4); }}Copy the code

Output result:

Set 1: [SPRING, FALL, WINTER]
Set 2: [SUMMER]
Set 3: [SPRING, SUMMER, FALL, WINTER]
Set 4: [SUMMER, FALL, WINTER]
Copy the code

EnumMap

The inheritance system diagram of EnumMap is as follows:

EnumMap also implements the Map interface, which also has these advantages over HashMap:

  • Consumes less memory
  • More efficient
  • Predictable traversal order
  • Reject the null

EnumMap is a high-performance implementation of Map. Its common approach is identical to that of a HashMap, with the only constraint being enumeration correlation.

Look at the examples, the most practical:

public class EnumTest {
    public static void main(String[] args) {
        Map<SeasonEnum, String> map = new EnumMap<>(SeasonEnum.class);
        map.put(SeasonEnum.SPRING, "Spring");
        map.put(SeasonEnum.SUMMER, "Summer");
        map.put(SeasonEnum.FALL, "Autumn");
        map.put(SeasonEnum.WINTER, "Winter"); System.out.println(map); System.out.println(map.get(SeasonEnum.SPRING)); }}Copy the code

The results

{SPRING= SPRING, SUMMER= SUMMER, FALL= autumn, WINTER= WINTERCopy the code

Ix. To be updated

There are key points about enumeration, dear friends, do you have anything to add?

Reference and thanks

  • An in-depth analysis of enumerations in Java
  • An in-depth analysis of Java enumeration types — thread safety and serialization of enumerations
  • Why do I recommend using enumerations to implement singletons?
  • In-depth understanding of Java enumeration types (EnUms)
  • Understand Java enumerations in depth
  • EnumSet in Java
  • Java enumeration (enum) explains the seven common uses
  • Ideas for Java Programming

Personal public account

  • If you are a good boy who loves learning, you can follow my public account and study and discuss with me.
  • If you feel that this article is not correct, you can comment, you can also follow my public account, private chat me, we learn and progress together.