About enum

What is an enum

Enumeration type. Enumeration class. Internally, a class that inherits from the java.lang.Enum class. [^ 1]

[^ 1]: Inheritance of java.lang.Enum is done by the compiler. Programmers cannot explicitly inherit classes.

For more information on enums, see Chapter 6 of the book "Effective Java". The author, Joshua Bloch, is the spec lead for JSR 201.

Problems solved by enums

Before enum

Initially, constant declarations for the sole purpose of distinguishing were described by the int enum pattern [^ 2].

CalendarConst.java


public final static int JANUARY = 0;
public final static int FEBRUARY = 1;
public final static int MARCH = 2;
public final static int APRIL = 3;
public final static int MAY = 4;
public final static int JUNE = 5;
public final static int JULY = 6;
public final static int AUGUST = 7;
public final static int SEPTEMBER = 8;
public final static int OCTOBER = 9;
public final static int NOVEMBER = 10;
public final static int DECEMBER = 11;
public final static int UNDECIMBER = 12;

The int enum pattern was effective in preventing magic numbers from appearing, but it had the following problems.

  1. No type guarantee Since it is an int, it is possible to make meaningless descriptions such as passing an irrelevant int value where necessary or adding two constants.

  2. There is no namespace You must prefix the constant with a string to avoid conflicting with other int enums.

  3. Vulnerability The int enumeration is a compile-time constant. If a new constant is added between two existing constants or the order is changed, the client must be recompiled. If you don't compile it, you can run it, but the behavior is unpredictable.

  4. The output value has no information value All outputs are numeric. I don't know what it means, and I don't even know what its type is.

[^ 2]: Currently an anti-pattern.

Type safe enum pattern

The type-safe enum pattern solves the problem of the int enum pattern. The enumeration constants are provided in one Singleton class.

MonthEnum.java


public class MonthEnum {

    private final String name;
    private final int ordinal;

    private Month(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }

    public String name() {
        return name;
    }

    public int getValue()
    {
        return ordinal() + 1;
    }

    public String toString() {
        return name;
    }

    public static final Month JANUARY = new Month("JANUARY", 0);
    public static final Month FEBRUARY = new Month("FEBRUARY", 1);
    public static final Month MARCH = new Month("MARCH", 2);
    public static final Month APRIL = new Month("APRIL", 3);
    public static final Month MAY = new Month("MAY", 4);
    public static final Month JUNE = new Month("JUNE", 5);
    public static final Month JULY = new Month("JULY", 6);
    public static final Month AUGUST = new Month("AUGUST", 7);
    public static final Month SEPTEMBER = new Month("SEPTEMBER", 8);
    public static final Month OCTOBER = new Month("OCTOBER", 9);
    public static final Month NOVEMBER = new Month("NOVEMBER", 10);
    public static final Month DECEMBER = new Month("DECEMBER", 11);
}

This is the standard description method before the advent of enums (before Java 5).

enum In Java5 and later, you can use enum class (enumeration type).

Month.java



public enum Month {

    JANUARY,
    FEBRUARY,
    MARCH,
    APRIL,
    MAY,
    JUNE,
    JULY,
    AUGUST,
    SEPTEMBER,
    OCTOBER,
    NOVEMBER,
    DECEMBER;

    public int getValue() {
        return ordinal() + 1;
    }

}

Although it is a concise description, it is an extension of the type-safe enum pattern in principle. You can confirm that the type-safe enum pattern is applied by decompiling the class file that compiles the enum class. The decompilation result is shown below.

Month.jad


public final class Month extends Enum
{

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

    public int getValue()
    {
        return ordinal() + 1;
    }

    public static Month[] values()
    {
        Month amonth[];
        int i;
        Month amonth1[];
        System.arraycopy(amonth = ENUM$VALUES, 0, amonth1 = new Month[i = amonth.length], 0, i);
        return amonth1;
    }

    public static Month valueOf(String s)
    {
        return (Month)Enum.valueOf(g06_enum/Month, s);
    }

    public static final Month JANUARY;
    public static final Month FEBRUARY;
    public static final Month MARCH;
    public static final Month APRIL;
    public static final Month MAY;
    public static final Month JUNE;
    public static final Month JULY;
    public static final Month AUGUST;
    public static final Month SEPTEMBER;
    public static final Month OCTOBER;
    public static final Month NOVEMBER;
    public static final Month DECEMBER;
    private static final Month ENUM$VALUES[];

    static 
    {
        JANUARY = new Month("JANUARY", 0);
        FEBRUARY = new Month("FEBRUARY", 1);
        MARCH = new Month("MARCH", 2);
        APRIL = new Month("APRIL", 3);
        MAY = new Month("MAY", 4);
        JUNE = new Month("JUNE", 5);
        JULY = new Month("JULY", 6);
        AUGUST = new Month("AUGUST", 7);
        SEPTEMBER = new Month("SEPTEMBER", 8);
        OCTOBER = new Month("OCTOBER", 9);
        NOVEMBER = new Month("NOVEMBER", 10);
        DECEMBER = new Month("DECEMBER", 11);
        ENUM$VALUES = (new Month[] {
            JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST, SEPTEMBER, OCTOBER, 
            NOVEMBER, DECEMBER
        });
    }
}

It is a Singleton class that inherits the Enum class by applying the type-safe enum pattern. The values and valueOf methods, ENUM $ VALUES, etc. are automatically generated by the compiler. [^ 3]

[^ 3]: The getValue I created earlier is an instance method, but values and valueOf are class methods of the Month class.

What you can do with enum

Definition of constructor with arguments

Month.java


public enum Month {

    JANUARY(1),
    FEBRUARY(2),
    MARCH(3),

    private int monthNumber;

    private Month(int param) {
        monthNumber = param;
    }
}

It is compiled as follows.

Month.jad


public final class Month extends Enum
{
    private Month(String s, int i, int param)
    {
        super(s, i);
        monthNumber = param;
    }

    public static Month[] values(){/*abridgement*/}

    public static Month valueOf(String s){/*abridgement*/}

    public static final Month JANUARY;
    public static final Month FEBRUARY;
    public static final Month MARCH;
    private int monthNumber;
    private static final Month ENUM$VALUES[];

    static 
    {
        JANUARY = new Month("JANUARY", 0, 1);
        FEBRUARY = new Month("FEBRUARY", 1, 2);
        MARCH = new Month("MARCH", 2, 3);
        ENUM$VALUES = (new Month[] {
            JANUARY, FEBRUARY, MARCH
        });
    }
}

Use of Enum class

Enum API can be used because it has an inheritance relationship with the java.lang.Enum class. ..

Recommended Posts

About enum
About =
[Java] About enum type
About method.invoke
About Kotlin
About attr_accessor
About Hinemos
About inheritance
About params
About Docker
enum definition
About form_for
About Spring ③
About polymorphism
About Optional
About hashes
About JitPack
About Dockerfile
About this ()
About devise
About encapsulation
[Java] enum
About Docker
About JAVA_HOME
About active_hash
About static
About exceptions
About scope
[Maven] About Maven
About exception handling
Review about bundler
About Java interface
[Java] About Java 12 features
About Rails routing
About cyclomatic complexity
Enum (enumeration type)
About exception handling
About Ruby symbols
About array multiplication
[Java] About arrays
About HotSpot VM
About ruby ​​form
[Swift] About generics
About class inheritance.
About Spring AOP
About Ruby Hashes
About singular methods
About getter setter
About build tools
About MacinCloud introduction
[Note] About nil
About keyword arguments
Enum review notes
Chew about API
[About double hash]
About installing Cocoapods
Something about java
Where about java
About HttpServlet () methods
About Java features
About ActiveRecord :: PendingMigrationError