[Enum] detailed explanation of enumeration classes in Java

1. What is enumeration?

Enumeration is a named collection of integer constants used to declare a set of constants with identifiers.
Enumeration is very common in daily life, such as gender, four seasons, week, month. Similarly, when a variable has several fixed possible values, it can be defined as an enumeration type.

Before JDK 1.5, there was no enumeration type. At that time, it was generally replaced by interface constants. For example:

public interface SeasonConstant {
	Integer SPRING = 1;
	Integer SUMMER = 2;
	Integer AUTUMN = 3;
	Integer WINTER = 4;
}

There is nothing wrong with this definition, but it has many shortcomings, such as not much benefit in type safety and ease of use. If there are variables that define the same int value, it is easy to be confused, and the compiler will not issue any warnings. Therefore, this method is not advocated after enumeration.

In JDK 1.5, a new feature enumeration is introduced, and the keyword enum is used to represent this type, which can more closely represent constants. Of course, in practical use, enumeration type can also be used as a specification to ensure the safety of program parameters and compile detection.

In Java, enumeration is at the same level as interface and class, except for different keywords. Moreover, enumeration is also a kind, but this kind inherits Java Lang. enum class.

OK, let's take a look at how to define enumeration types~~

2. Define enumeration type

So, how do we define enumeration types?

Since the enumeration type is a special class type, we can also define the enumeration type as we define the class. When defining enumeration types, they can be defined in a separate file or inside other classes.

Now, we use the enumeration type to redefine the above constants and define the constants from spring to winter. For example:

public enum SeasonEnum {
	// spring
    SPRING
    ,
    // summer
    SUMMER
    ,
    // autumn
    AUTUMN
    ,
    // winter
    WINTER
    ;
}

Enumeration class (enumeration can be called enumeration class). There are four enumeration items in SeasonEnum: SPRING, SUMMER, AUTUMN and WINTER. They are instances of this enumeration class. That is, the enumeration class SeasonEnum has four instance objects.

Note: when defining enumeration items, multiple enumeration items are separated by commas, and a semicolon is required after the last enumeration item! However, if there are only enumeration items (no constructors, methods, instance variables) in the enumeration class, you can omit the semicolon!

After defining the above enumeration type, how can we use it?

You cannot use new to create an object of an enumeration class because its constructor is decorated with private.

Use the writing method of enumeration class: enumeration class name Enumeration item (the enumeration item in the enumeration class is the instance in the enumeration class). Namely:

public enum SeasonEnum {
    SPRING, SUMMER, AUTUMN, WINTER;

    public static void main(String[] args) {
        SeasonEnum seasonEnum = SeasonEnum.SPRING;
    }
}

Enumeration types and switch statements

Use enumeration types in switch statements to make them more readable. For example:

Define an enumeration type:

public enum SeasonEnum {
    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;
}

Test:

public class TestEnum {
	
	// Judge whether it is the four seasons
    public void judgeSeason(SeasonEnum seasonEnum) {
        switch (seasonEnum) {
            case SPRING:
                System.out.println("It's spring");
                break;
            case SUMMER:
                System.out.println("It's summer");
                break;
            case AUTUMN:
                System.out.println("It's autumn");
                break;
            case WINTER:
                System.out.println("It's winter");
                break;
            default:
                System.out.println("This is the wrong season");
        }
    }

    public static void main(String[] args) {
        TestEnum testEnum = new TestEnum();
        SeasonEnum spring = SeasonEnum.SPRING;

        testEnum.judgeSeason(spring);
    }
}

The input parameter to the TestEnum#judgeSeason(SeasonEnum) method is a SeasonEnum type. When calling this method, if the type passed in is not the type of SeasonEnum, an error will be reported during compilation, which ensures the safety of program parameters.

Note: enumeration class names cannot be used in switch case statements. For example: case seasonEnum SPRING:. Otherwise, an error will be reported during compilation (an enum switch case label must be the...). Because the compiler will determine each enumeration type according to the type of seasonEnum in the switch, the enumeration option of the same type as seasonEnum must be given directly in the case, and the enumeration type can no longer be included.

Looking back, let's look at the usage of enumeration: enumeration class name Enumeration item
So, why can it be used like this? Just look at the implementation principle of enumeration

3. Enumeration implementation principle

Use jad decompile tool to compile the above generated SeasonEnum enumeration class Decompile the class file.
The decompiled results are as follows:

package com.tiandy.zzc.design.enums;

public final class SeasonEnum extends Enum    // Inherited Enum class
{
	// ---------- javac ----------
    public static SeasonEnum[] values()
    {
        return (SeasonEnum[])$VALUES.clone();
    }

    public static SeasonEnum valueOf(String name)
    {
        return (SeasonEnum)Enum.valueOf(com/tiandy/zzc/design/enums/SeasonEnum, name);
    }

	// Private construction method
    private SeasonEnum(String s, int i)
    {
        super(s, i);
    }

	// static const 
    public static final SeasonEnum SPRING;
    public static final SeasonEnum SUMMER;
    public static final SeasonEnum AUTUMN;
    public static final SeasonEnum WINTER;
    private static final SeasonEnum $VALUES[];
	
	// Initialize static code blocks
    static 
    {
        SPRING = new SeasonEnum("SPRING", 0);
        SUMMER = new SeasonEnum("SUMMER", 1);
        AUTUMN = new SeasonEnum("AUTUMN", 2);
        WINTER = new SeasonEnum("WINTER", 3);
        $VALUES = (new SeasonEnum[] {
            SPRING, SUMMER, AUTUMN, WINTER
        });
    }
}

From the perspective of decompiled code, the following points are summarized:

  1. The compiler does generate a SeasonEnum class for us, and this class inherits Java Lang. enum class, modified by finally keyword;
  2. During compilation, we also generated four static constants corresponding to four enumeration instances in the enumeration class
  3. Compile time also helps us generate two static methods: values() and valueOf()
  4. The compiler also helps us generate a private, parameterized constructor: private SeasonEnum(String s, int i). One is the name of the enumeration object; The other is the index of enumeration objects

[summary]: the enumeration type defined with the keyword enum will be converted into a real class after compilation. In this class, there will be each corresponding instance object with constant defined in the enumeration type. As mentioned above, the SPRING enumeration constant corresponds to the public static final SeasonEnum SPRING static constant in the class

values() method

Through the above decompiled code, we know that after compilation, the compiler generates values() and valueof() methods for us. View Java Lang. enum class. It is found that there is no values() method, but there is a valueof() method.

The values() method is used to obtain all instances in the enumeration class and return them as an array. For example:

public enum SeasonEnum {

    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;

    public static void main(String[] args) {
        SeasonEnum[] values = SeasonEnum.values();
        // [SPRING, SUMMER, AUTUMN, WINTER]
        System.out.println(Arrays.toString(values));
    }

}

valueof() method

Although Java There is a valueof () method in lang. enum class, but the input parameters of these two methods are different. The valueof () method generated by the compiler has only one parameter and will call Java valueof() method with two parameters in lang. enum class.

The valueof() method is used to obtain enumeration instances by name. For example:

public enum SeasonEnum {

    SPRING,
    SUMMER,
    AUTUMN,
    WINTER;

    public static void main(String[] args) {
        SeasonEnum seasonEnum = SeasonEnum.valueOf("AUTUMN");
        // AUTUMN
        System.out.println(seasonEnum);
    }

}

Why does the above example print "AUTUMN"?
Because Java The toString() method is overridden in the lang. enum class. This method only returns the name of the enumerated instance in the enumeration class.

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
    
    // Enumeration constant name
    private final String name;
    
    ...
    
	public String toString() {
	    return name;
	}
}

Keywords: Java

Added by leafer on Wed, 05 Jan 2022 05:41:28 +0200