Motivation

  • Understand how to write an enum type in Java.

Basic definitions and instance methods

public class Main {
    public static void main(String[] args) {
        try {
            System.out.printf("LogLevel.valueOf(): %s\n", LogLevel.valueOf("LOW"));
            System.out.printf("LogLevel.valueOf().getClass(): %s\n", LogLevel.valueOf("LOW").getClass());
            System.out.printf("LogLevel.valueOf(): %s\n", LogLevel.valueOf("NONE"));
        } catch (Exception e){
            System.out.println(e);
        }
        System.out.println();


        // Testing enum's constructor
        for (LogLevel logLevel: LogLevel.values()) {
            System.out.println("--------------------START-----------------------");
            System.out.printf("# Log level: %s\n", logLevel);
            System.out.printf("instance of LogLevel?: %b\n",logLevel instanceof LogLevel);
            System.out.println();
            // Testing getter method
            System.out.println("## Testing sefl-implemented instance methods");
            System.out.printf("getLogLevel(): %s\n", logLevel.getLogLevel());
            System.out.println();
            // Testing enum instance methods
            System.out.println("## Testing common instance methods");
            System.out.printf("toString(): %s\n", logLevel.toString());
            System.out.printf("name(): %s\n", logLevel.name());
            System.out.printf("ordinal(): %s\n", logLevel.ordinal());

            System.out.println("---------------------END------------------------");
            System.out.println();
        }
    }
}

public enum LogLevel {
    // These enum constants use the constructor defined below.
    LOW("low"),
    MEDIUM("medium"),
    HIGH("high");

    private final String logLevel;

    LogLevel(String logLevel) {
        this.logLevel = logLevel;
    }

    public String getLogLevel() {
        return this.logLevel;
    }
}

Output

$ java Main.java
LogLevel.valueOf(): LOW
LogLevel.valueOf().getClass(): class LogLevel
java.lang.IllegalArgumentException: No enum constant LogLevel.NONE

--------------------START-----------------------
# Log level: LOW
instance of LogLevel?: true

## Testing sefl-implemented instance methods
getLogLevel(): LOW

## Testing common instance methods
toString(): LOW
name(): LOW
ordinal(): 0
---------------------END------------------------

--------------------START-----------------------
# Log level: MEDIUM
instance of LogLevel?: true

## Testing sefl-implemented instance methods
getLogLevel(): MEDIUM

## Testing common instance methods
toString(): MEDIUM
name(): MEDIUM
ordinal(): 1
---------------------END------------------------

--------------------START-----------------------
# Log level: HIGH
instance of LogLevel?: true

## Testing sefl-implemented instance methods
getLogLevel(): HIGH

## Testing common instance methods
toString(): HIGH
name(): HIGH
ordinal(): 2
---------------------END------------------------

Conditional statement using enum (switch)

with Java 17

public class Main {
    public static void main(String[] args) {
        LogLevel currentLevel = LogLevel.LOW;
        LogLevel.detectCurrentLogLevel(currentLevel);
    }

}

public enum LogLevel {
    // These enum constants use the constructor defined below.
    LOW("low"),
    MEDIUM("medium"),
    HIGH("high");

    private final String logLevel;

    LogLevel(String logLevel) {
        this.logLevel = logLevel;
    }

    public String getLogLevel() {
        return this.logLevel;
    }

    public static void detectCurrentLogLevel(LogLevel currentLevel) {
        switch (currentLevel) {
            case LOW, MEDIUM -> {
                System.out.printf("Current level: %s\n", currentLevel);
            }
            case HIGH -> {
                System.out.printf("Current level: %s\n", currentLevel);
            }
            default -> {
                // never reached
                System.out.printf("Unknow log level");
            }
        }
    }
}

with Java 11

public class Main {
    public static void main(String[] args) {
        LogLevel currentLevel = LogLevel.LOW;
        LogLevel.detectCurrentLogLevel(currentLevel);
    }

}

public enum LogLevel {
    // These enum constants use the constructor defined below.
    LOW("low"),
    MEDIUM("medium"),
    HIGH("high");

    private final String logLevel;

    LogLevel(String logLevel) {
        this.logLevel = logLevel;
    }

    public String getLogLevel() {
        return this.logLevel;
    }

    public static void detectCurrentLogLevel(LogLevel currentLevel) {
        switch (currentLevel) {
            case LOW:
                System.out.printf("Current level: %s\n", currentLevel);
                break;
            case MEDIUM:
                System.out.printf("Current level: %s\n", currentLevel);
                break;
            case HIGH:
                System.out.printf("Current level: %s\n", currentLevel);
                break;
            default:
                // never reached
                System.out.printf("Unknow log level");
        }
    }
}

Output

$ java Main.java
Current level: LOW

Note

We cannot use switch-case expression in Java 11 but can use switch-case statements (break keyword is necessary to stop fall through).

Java SE 12 introduced switch expressions, which (like all expressions) evaluate to a single value, and can be used in statements. It also introduced “arrow case” labels that eliminate the need for break statements to prevent fall through.

EnumSet

import java.util.EnumSet;

public class Main {
    // Create an union set from enum constants
    private static final EnumSet<LogLevel> acceptableLevel = EnumSet.of(LogLevel.LOW, LogLevel.MEDIUM);

    public static boolean isAcceptableLevel(LogLevel level) {
        return acceptableLevel.contains(level);
    }

    public static void main(String[] args) {
        var currentLevel = LogLevel.HIGH;

        if (isAcceptableLevel(currentLevel)) {
            System.out.printf("Safe to ignore\n Level is %s\n", currentLevel.toString());
        } else {
            System.out.printf("Something wrong is happening!!\nLevel is %s\n", currentLevel.toString());
        }
    }

}

public enum LogLevel {
    // These enum constants use the constructor defined below.
    LOW("low"),
    MEDIUM("medium"),
    HIGH("high");

    private final String logLevel;

    LogLevel(String logLevel) {
        this.logLevel = logLevel;
    }

    public String getLogLevel() {
        return this.logLevel;
    }
}

Output

$ java Main.java
Something wrong is happening!!
Level is HIGH

EnumMap

import java.util.EnumMap;

public class Main {

    public static void main(String[] args) {
        // Create a map accpeting keys defined in the enum type
        EnumMap<LogLevel,String> logLevelMap = new EnumMap<>(LogLevel.class);
        System.out.println("# initial map");
        System.out.println(logLevelMap);

        System.out.println("# value filled map");
        logLevelMap.put(LogLevel.LOW, "low level");
        logLevelMap.put(LogLevel.MEDIUM, "medium level");
        logLevelMap.put(LogLevel.HIGH, "high level");
        System.out.println(logLevelMap);
    }
}

public enum LogLevel {
    // These enum constants use the constructor defined below.
    LOW("low"),
    MEDIUM("medium"),
    HIGH("high");

    private final String logLevel;

    LogLevel(String logLevel) {
        this.logLevel = logLevel;
    }

    public String getLogLevel() {
        return this.logLevel;
    }
}

Output

$ java Main.java
# initial map
{}
# value filled map
{LOW=low level, MEDIUM=medium level, HIGH=high level}