Fundamentals 14 min read

Master Java Enums: From Basics to Advanced Design Patterns

This article explains Java enums, their advantages over constants, demonstrates custom methods, comparisons, switch usage, advanced features like EnumSet, EnumMap, JSON serialization, and shows how enums can implement design patterns such as Singleton and Strategy with complete code examples.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Master Java Enums: From Basics to Advanced Design Patterns

Overview

In this article we explore what Java enums are, the problems they solve, and how to use them to implement various design patterns.

1. Basic Enum Definition

package shuang.kou.enumdemo.enumtest;

public enum PizzaStatus {
    ORDERED,
    READY,
    DELIVERED;
}

Using the enum improves readability, enables compile‑time checks, and prevents invalid values.

System.out.println(PizzaStatus.ORDERED.name()); // ORDERED
System.out.println(PizzaStatus.ORDERED); // ORDERED
System.out.println(PizzaStatus.ORDERED.name().getClass()); // class java.lang.String
System.out.println(PizzaStatus.ORDERED.getClass()); // class shuang.kou.enumdemo.enumtest.PizzaStatus

2. Adding Custom Methods to Enums

public class Pizza {
    private PizzaStatus status;
    public enum PizzaStatus {
        ORDERED,
        READY,
        DELIVERED;
    }

    public boolean isDeliverable() {
        if (getStatus() == PizzaStatus.READY) {
            return true;
        }
        return false;
    }
    // getters and setters omitted for brevity
}

3. Comparing Enums with ==

Because each enum constant is a singleton, the == operator is safe and avoids NullPointerException.

if (testPz.getStatus().equals(Pizza.PizzaStatus.DELIVERED)) {
    // risky, may throw NPE if status is null
}
if (testPz.getStatus() == Pizza.PizzaStatus.DELIVERED) {
    // safe comparison
}

4. Using Enums in switch Statements

public int getDeliveryTimeInDays() {
    switch (status) {
        case ORDERED: return 5;
        case READY:   return 2;
        case DELIVERED: return 0;
    }
    return 0;
}

5. Enum Fields, Methods, and Constructors

public class Pizza {
    private PizzaStatus status;
    public enum PizzaStatus {
        ORDERED(5) {
            @Override public boolean isOrdered() { return true; }
        },
        READY(2) {
            @Override public boolean isReady() { return true; }
        },
        DELIVERED(0) {
            @Override public boolean isDelivered() { return true; }
        };

        private int timeToDelivery;
        public boolean isOrdered() { return false; }
        public boolean isReady() { return false; }
        public boolean isDelivered() { return false; }
        public int getTimeToDelivery() { return timeToDelivery; }
        PizzaStatus(int timeToDelivery) { this.timeToDelivery = timeToDelivery; }
    }

    public boolean isDeliverable() { return this.status.isReady(); }
    public void printTimeToDeliver() {
        System.out.println("Time to delivery is " + this.getStatus().getTimeToDelivery());
    }
    // getters and setters omitted
}

6. EnumSet and EnumMap

6.1 EnumSet

EnumSet

is a highly efficient set implementation for enum types, providing type‑safe alternatives to bit‑flags.

public class Pizza {
    private static EnumSet<PizzaStatus> undeliveredPizzaStatuses =
        EnumSet.of(PizzaStatus.ORDERED, PizzaStatus.READY);
    // other code omitted
}

6.2 EnumMap

EnumMap

is a compact map implementation that uses an array internally.

public static EnumMap<PizzaStatus, List<Pizza>> groupPizzaByStatus(List<Pizza> pizzaList) {
    EnumMap<PizzaStatus, List<Pizza>> pzByStatus =
        new EnumMap<>(PizzaStatus.class);
    for (Pizza pz : pizzaList) {
        PizzaStatus status = pz.getStatus();
        pzByStatus.computeIfAbsent(status, k -> new ArrayList<>()).add(pz);
    }
    return pzByStatus;
}

7. Implementing Design Patterns with Enums

7.1 Singleton Pattern

public enum PizzaDeliverySystemConfiguration {
    INSTANCE;
    private PizzaDeliveryStrategy deliveryStrategy = PizzaDeliveryStrategy.NORMAL;
    public static PizzaDeliverySystemConfiguration getInstance() { return INSTANCE; }
    public PizzaDeliveryStrategy getDeliveryStrategy() { return deliveryStrategy; }
}

7.2 Strategy Pattern

public enum PizzaDeliveryStrategy {
    EXPRESS {
        @Override public void deliver(Pizza pz) {
            System.out.println("Pizza will be delivered in express mode");
        }
    },
    NORMAL {
        @Override public void deliver(Pizza pz) {
            System.out.println("Pizza will be delivered in normal mode");
        }
    };
    public abstract void deliver(Pizza pz);
}

8. Java 8 Enhancements

Using streams and lambdas makes the collection utilities concise.

public static List<Pizza> getAllUndeliveredPizzas(List<Pizza> input) {
    return input.stream()
        .filter(s -> !undeliveredPizzaStatuses.contains(s.getStatus()))
        .collect(Collectors.toList());
}

public static EnumMap<PizzaStatus, List<Pizza>> groupPizzaByStatus(List<Pizza> pzList) {
    return pzList.stream().collect(
        Collectors.groupingBy(Pizza::getStatus,
            () -> new EnumMap<>(PizzaStatus.class),
            Collectors.toList()));
}

9. JSON Serialization of Enums

Jackson can serialize enums as JSON objects using @JsonFormat(shape = JsonFormat.Shape.OBJECT).

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum PizzaStatus {
    ORDERED(5) { @Override public boolean isOrdered() { return true; } },
    READY(2)   { @Override public boolean isReady()   { return true; } },
    DELIVERED(0){ @Override public boolean isDelivered(){ return true; } };
    private int timeToDelivery;
    @JsonProperty("timeToDelivery")
    public int getTimeToDelivery() { return timeToDelivery; }
    // other methods omitted
}

10. Additional Example: PinType Enum

public enum PinType {
    REGISTER(100000, "注册使用"),
    FORGET_PASSWORD(100001, "忘记密码使用"),
    UPDATE_PHONE_NUMBER(100002, "更新手机号码使用");

    private final int code;
    private final String message;
    PinType(int code, String message) { this.code = code; this.message = message; }
    public int getCode() { return code; }
    public String getMessage() { return message; }
    @Override public String toString() {
        return "PinType{code=" + code + ", message='" + message + "'}";
    }
}

System.out.println(PinType.FORGET_PASSWORD.getCode());
System.out.println(PinType.FORGET_PASSWORD.getMessage());
System.out.println(PinType.FORGET_PASSWORD.toString());

11. Conclusion

The article covered Java enums from basic definitions to advanced applications, demonstrating their power in type safety, collections, JSON handling, and classic design patterns.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Design PatternsJavaenumSingletonstrategyEnumMapEnumSet
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.