This is the 12th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

Enumerations, or enumerations, are often used to indicate sets that can be scoped, such as gender, season, week, month, etc.

Enumerations didn’t appear until JDK 1.5. Before enumerations, we used constants to represent certain values, such as

    public static final Integer SPRING = 1;
    public static final Integer SUMMER = 2;
    public static final Integer FALL = 3;
    public static final Integer WINTER = 4;
Copy the code

We can use an enumeration class, which is the simplest enumeration.

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

So what are the advantages of enumerating classes over defining constants?

As you can see from the code above, seasons represented by constants are of type Integer, which is a very large data range. Using enumerations limits the scope of the data. Enumerations can be thought of as a collection of constants, and the data does not change much. Using enumerations makes the semantics more explicit because the data domain is not large.

There are a few things to note about enumerated classes:

  1. Enum has the same status as class and interface
  2. Enum classes defined using enum inherit from java.lang. enum by default, instead of inheriting from Object. Enumerated classes can implement one or more interfaces and cannot inherit from other classes.
  3. All instances of the enumerated class must be displayed on the first line, without the use of the new keyword, and without the explicit call to the constructor. Automatically add public static final decoration.
  4. The constructor of an enumerated class can only be private.

On point 4, I would say that enumerated classes are defined in singletons. Singletons require the constructor to be private and do not allow the creation of new objects outside of the constructor. It was already created at the time we defined it, so there is no need or way to continue creating new objects externally. Therefore, the constructor needs to be privatized.

An enumeration class is simply a castrated class that allows you to create objects, whereas an enumeration class specifies which objects to create when it is defined. You don’t show code creation because the JVM automatically adds it to you. We’ll see what happens when the enumeration class is decompiled.

Properties and methods can be defined in enumerated classes.

enum Season{

    SPRING("Spring"."A year's plan begins in spring."),SUMMER("Summer"."It's hot in summer."),
    FALL("Autumn"."Autumn water and sky are the same color."),WINTER("Winter"."It's so cold in winter.");

    // Add the name of the enumeration object
    private final String name;

    // Add a description of the enumeration object
    private final String desc;

    private Season(String name,String desc){
        this.name = name;
        this.desc = desc;
    }

    public String getName(a){
        return name;
    }

    public String getDesc(a){
        returndesc; }}Copy the code

As you can see, there is a private constructor with parameters, so the enumeration can be assigned directly when defining the enumeration, while the call to create the object is done automatically by the VIRTUAL machine, and more attributes can be added, so we can use the enumeration as normal.

// Get all enumerated objects, return arrays
Season[] values = Season.values();
for (Season season : values) {
System.out.println(season.getName() + ":"+ season.getDesc()); } Spring: the plan of the year depends on spring summer: summer is very hot ~ Autumn: autumn water is the same color sky winter: winter is very cold ~Copy the code

Implement abstract methods in enumeration classes

This is definitely a little confusing. We know that classes that contain abstract methods are abstract classes, so why can enumerations contain abstract methods without being abstract? Let’s look at the implementation first, and we’ll talk about why.

enum Season{

    SPRING("Spring"."A year's plan begins in spring.") {
        @Override
        public Season getNextSeason(a) {
            return Season.valueOf("SUMMER");
        }
    },SUMMER("Summer"."It's hot in summer.") {
        @Override
        public Season getNextSeason(a) {
            return Season.valueOf("FALL"); }},... Omit... Omit... omit// Defines an abstract method to get the next season
    public abstract Season getNextSeason(a);
}
Copy the code

The test code is as follows

public static void main(String[] args) {
    String name = Season.SPRING.getNextSeason().getName();
    System.out.println(name); / / in the summer
}
Copy the code

If you feel vaguely familiar, let’s decompile and take a look at the internals of enumerated classes.

Let’s take a simple example of how enumerated classes work. Just take the simplest enumeration to illustrate the situation.

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

Take a look at the decompiled code. The decompiled tool I used was JAD.

public final class SeasonEnum extends Enum
{

    public static SeasonEnum[] values()
    {
        return (SeasonEnum[])$VALUES.clone();
    }

    public static SeasonEnum valueOf(String s)
    {
        return (SeasonEnum)Enum.valueOf(SeasonEnum, s);
    }

    private SeasonEnum(String s, int i)
    {
        super(s, i);
    }

    public static final SeasonEnum SPRING;
    public static final SeasonEnum SUMMER;
    public static final SeasonEnum FALL;
    public static final SeasonEnum WINTER;
    private static final SeasonEnum $VALUES[];

    static 
    {
        SPRING = new SeasonEnum("SPRING".0);
        SUMMER = new SeasonEnum("SUMMER".1);
        FALL = new SeasonEnum("FALL".2);
        WINTER = new SeasonEnum("WINTER".3);
        $VALUES = (newSeasonEnum[] { SPRING, SUMMER, FALL, WINTER }); }}Copy the code

We can see that the enumeration class is essentially a singleton class that inherits the Enum, and the enumeration object we define is initialized in a static block of code. We can also see that the implementation of the Values method returns an array of instance objects, that is, an array of enumeration objects, and the valueOf method takes a string, Returns the enumeration object of the string, or an error if it cannot be found.

We can see why we can define abstract methods in enumerated classes. We implement abstract methods using inner classes, and each object is created with the corresponding abstract method. In the same way, enumerated classes can implement interfaces that are not demonstrated here.

Having said so much, I also know the benefits of enumeration, but I have to say that in my actual project, the use of enumeration classes is really not much, let’s take a look at the use of enumeration classes, later this need can be considered using enumeration to achieve.

The switch statement’s support for enumerations didn’t come until JDK 1.5, when enumerations became available. Let’s look at specific uses.

/** * Server response code */
public enum ResponseCode {

    SUCCESS(200."Access successful"),FAIL(404."Page does not exist"),ERROR(500."Server internal error");

    private Integer num;
    private String desc;

    private ResponseCode(Integer num,String desc){
        this.num = num;
        this.desc = desc;
    }

    public Integer getNum(a) {
        return num;
    }

    public String getDesc(a) {
        return desc;
    }

    /* * Returns the enumeration object */
    public static ResponseCode getByNum(Integer num){
        for(ResponseCode code : values()){
            if(code.getNum().equals(num)){
                returncode; }}return null; }} ============= test =====================public static void main(String[] args) {
        ResponseCode code = ResponseCode.getByNum(200);
        switch (code) {
        case SUCCESS:
            System.out.println("Success");
            break;

        default:
            break; }}Copy the code

Enumerations have only been used in one of my projects to keep track of dictionary values. For example, I wrote a utility class to keep track of all dictionary-related data used in the project. Like this

public class Keys {
    enum Sex{
        MALE,FEMALE;
    }
    enum State{
        SUCCESS,FAIL;
    }
    enum Month{}enum Week{}public static void main(String[] args) { Keys.Sex.MALE.name(); }}Copy the code

However, it turns out that there is a better way to configure dictionaries than using enumerations above by creating a dictionary class that puts all the dictionary data in a table.