Java Enum

Special classes for defining collections of constants

📋 What is an Enum?

Enum is a special class that represents a group of constants. It provides type safety, prevents invalid values, and makes code more readable and maintainable.


// Simple enum definition
enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
                                    

Enum Features

🔒

Type Safety

Prevents invalid constant values

enum Status {
    ACTIVE, INACTIVE, PENDING
}
📚

Built-in Methods

Comes with useful methods

Status.valueOf("ACTIVE");
Status.values();
status.ordinal();
🏗️

Constructor Support

Can have fields and constructors

enum Size {
    SMALL(10), MEDIUM(20), LARGE(30);
    private int value;
}
⚙️

Methods

Can have custom methods

enum Planet {
    EARTH(5.976e+24);
    double getMass() { return mass; }
}

🔹 Basic Enum Usage

Creating and using simple enums:

// Define enum
enum TrafficLight {
    RED, YELLOW, GREEN
}

public class EnumExample {
    public static void main(String[] args) {
        // Using enum constants
        TrafficLight light = TrafficLight.RED;
        
        System.out.println("Current light: " + light);
        
        // Switch statement with enum
        switch (light) {
            case RED:
                System.out.println("Stop!");
                break;
            case YELLOW:
                System.out.println("Caution!");
                break;
            case GREEN:
                System.out.println("Go!");
                break;
        }
        
        // Built-in methods
        System.out.println("Ordinal of RED: " + TrafficLight.RED.ordinal());
        System.out.println("All values: ");
        for (TrafficLight tl : TrafficLight.values()) {
            System.out.println("- " + tl);
        }
        
        // valueOf method
        TrafficLight fromString = TrafficLight.valueOf("GREEN");
        System.out.println("From string: " + fromString);
    }
}

Output:

Current light: RED
Stop!
Ordinal of RED: 0
All values: 
- RED
- YELLOW
- GREEN
From string: GREEN

🔹 Enum with Fields and Constructor

Enums can have fields, constructors, and methods:

enum Planet {
    MERCURY(3.303e+23, 2.4397e6),
    VENUS(4.869e+24, 6.0518e6),
    EARTH(5.976e+24, 6.37814e6),
    MARS(6.421e+23, 3.3972e6);
    
    private final double mass;   // in kilograms
    private final double radius; // in meters
    
    // Constructor
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    
    // Methods
    public double getMass() {
        return mass;
    }
    
    public double getRadius() {
        return radius;
    }
    
    // Calculate surface gravity
    public double surfaceGravity() {
        final double G = 6.67300E-11;
        return G * mass / (radius * radius);
    }
    
    // Calculate weight on this planet
    public double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
}

public class PlanetExample {
    public static void main(String[] args) {
        double earthWeight = 70; // kg
        double mass = earthWeight / Planet.EARTH.surfaceGravity();
        
        System.out.println("Your weight on different planets:");
        for (Planet p : Planet.values()) {
            System.out.printf("Weight on %s: %.2f kg%n", 
                            p, p.surfaceWeight(mass));
        }
        
        System.out.println("\nPlanet details:");
        Planet earth = Planet.EARTH;
        System.out.printf("Earth mass: %.2e kg%n", earth.getMass());
        System.out.printf("Earth radius: %.2e m%n", earth.getRadius());
    }
}

Output:

Your weight on different planets:
Weight on MERCURY: 26.36 kg
Weight on VENUS: 63.21 kg
Weight on EARTH: 70.00 kg
Weight on MARS: 26.56 kg

Planet details:
Earth mass: 5.98e+24 kg
Earth radius: 6.38e+06 m

🔹 Enum with Abstract Methods

Enums can have abstract methods that each constant must implement:

enum Operation {
    PLUS("+") {
        public double apply(double x, double y) {
            return x + y;
        }
    },
    MINUS("-") {
        public double apply(double x, double y) {
            return x - y;
        }
    },
    MULTIPLY("*") {
        public double apply(double x, double y) {
            return x * y;
        }
    },
    DIVIDE("/") {
        public double apply(double x, double y) {
            return x / y;
        }
    };
    
    private final String symbol;
    
    Operation(String symbol) {
        this.symbol = symbol;
    }
    
    public String getSymbol() {
        return symbol;
    }
    
    // Abstract method - each constant must implement
    public abstract double apply(double x, double y);
    
    @Override
    public String toString() {
        return symbol;
    }
}

public class CalculatorExample {
    public static void main(String[] args) {
        double x = 10.0;
        double y = 3.0;
        
        System.out.println("Calculator operations:");
        for (Operation op : Operation.values()) {
            double result = op.apply(x, y);
            System.out.printf("%.1f %s %.1f = %.2f%n", 
                            x, op, y, result);
        }
        
        // Using specific operation
        Operation multiply = Operation.MULTIPLY;
        System.out.println("\nSpecific operation:");
        System.out.printf("5 %s 4 = %.1f%n", 
                        multiply, multiply.apply(5, 4));
    }
}

Output:

Calculator operations:
10.0 + 3.0 = 13.00
10.0 - 3.0 = 7.00
10.0 * 3.0 = 30.00
10.0 / 3.0 = 3.33

Specific operation:
5 * 4 = 20.0

🔹 Real-World Example: Order Status

A practical example using enums for order management:

enum OrderStatus {
    PENDING("Order received, processing...") {
        public OrderStatus next() {
            return CONFIRMED;
        }
    },
    CONFIRMED("Order confirmed, preparing...") {
        public OrderStatus next() {
            return SHIPPED;
        }
    },
    SHIPPED("Order shipped, in transit...") {
        public OrderStatus next() {
            return DELIVERED;
        }
    },
    DELIVERED("Order delivered successfully!") {
        public OrderStatus next() {
            return this; // Final state
        }
    },
    CANCELLED("Order cancelled") {
        public OrderStatus next() {
            return this; // Final state
        }
    };
    
    private final String description;
    
    OrderStatus(String description) {
        this.description = description;
    }
    
    public String getDescription() {
        return description;
    }
    
    public abstract OrderStatus next();
    
    public boolean canCancel() {
        return this == PENDING || this == CONFIRMED;
    }
}

class Order {
    private String orderId;
    private OrderStatus status;
    
    public Order(String orderId) {
        this.orderId = orderId;
        this.status = OrderStatus.PENDING;
    }
    
    public void processNext() {
        status = status.next();
        System.out.println("Order " + orderId + ": " + status.getDescription());
    }
    
    public void cancel() {
        if (status.canCancel()) {
            status = OrderStatus.CANCELLED;
            System.out.println("Order " + orderId + " cancelled");
        } else {
            System.out.println("Cannot cancel order " + orderId + " in " + status + " status");
        }
    }
    
    public OrderStatus getStatus() {
        return status;
    }
}

public class OrderExample {
    public static void main(String[] args) {
        Order order = new Order("ORD-001");
        
        System.out.println("Order lifecycle:");
        System.out.println("Initial: " + order.getStatus().getDescription());
        
        // Process through states
        order.processNext(); // CONFIRMED
        order.processNext(); // SHIPPED
        
        // Try to cancel (should fail)
        order.cancel();
        
        order.processNext(); // DELIVERED
        order.processNext(); // Still DELIVERED
        
        System.out.println("\nNew order cancellation:");
        Order order2 = new Order("ORD-002");
        order2.cancel(); // Should succeed
    }
}

Output:

Order lifecycle:
Initial: Order received, processing...
Order ORD-001: Order confirmed, preparing...
Order ORD-001: Order shipped, in transit...
Cannot cancel order ORD-001 in SHIPPED status
Order ORD-001: Order delivered successfully!
Order ORD-001: Order delivered successfully!

New order cancellation:
Order ORD-002 cancelled

🔹 Enum Best Practices

Guidelines for effective enum usage:

Best Practices:

  • Use for fixed sets: Days, months, status values, etc.
  • Make fields final: Enum constants should be immutable
  • Use descriptive names: ACTIVE instead of A, PENDING instead of P
  • Implement toString(): For better string representation
  • Consider EnumSet/EnumMap: For collections of enums

When to Use Enums:

  • Fixed set of constants (colors, directions, states)
  • Type-safe alternatives to int constants
  • Switch statement cases
  • Configuration options

🧠 Test Your Knowledge

What is the main advantage of using enums over constants?