Java › Enums

How would you handle adding behavior to an enum where the number of constants might grow very large or needs to be data-driven rather than hardcoded at compile time, and why might a class-based registry be more appropriate in that scenario?

Advanced

Answer

Enums are fundamentally a CLOSED, compile-time-fixed set of constants -- appropriate when the set of values is genuinely stable and known at compile time (like days of the week, or a fixed set of HTTP methods), but poorly suited to scenarios where the set of constants needs to grow dynamically at runtime (loaded from a database, a plugin system, or user configuration) since enum constants can't be added without recompiling the enum's source code itself -- for genuinely dynamic, extensible sets of named values with associated behavior, a regular class combined with a Map-based registry (mapping a String/code to an instance) provides the same lookup-by-key convenience while supporting runtime extensibility that a true enum structurally cannot.
// NOT well-suited to enum: currency codes that might be extended by configuration at runtime
public final class Currency {
    private static final Map<String, Currency> REGISTRY = new ConcurrentHashMap<>();
    private final String code;
    private Currency(String code) { this.code = code; }

    public static Currency register(String code) {
        return REGISTRY.computeIfAbsent(code, Currency::new);  // can grow dynamically, unlike an enum
    }
    public static Currency of(String code) { return REGISTRY.get(code); }
}
Real-world example A multi-tenant SaaS platform allowing each customer organization to define their own custom set of order-status values (impossible to know all of them at compile time) uses a class-based registry pattern with a Map-backed lookup instead of an enum, since new status values need to be added dynamically per-tenant without requiring a code deployment.

Common follow-ups: What functionality do you lose by switching from a true enum to this class-based registry pattern (like switch-statement exhaustiveness checking)?;How would EnumMap/EnumSet's performance benefits compare to this Map-based registry approach?