Enums & Records — Type-Safe Constants & Data Without Boilerplate

Enum ও Record — type-safe ধ্রুবক ও boilerplate-মুক্ত ডেটা

Read: ~28 min Intermediate 5 practice problems Live code runner

1. Two Modern Shortcuts

Two common shapes of type come up so often that Java gives them their own keyword:

  • Enum — a fixed, named set of instances. DayOfWeek, PaymentMethod, OrderStatus. Type-safe, self-documenting, and far safer than a bunch of int constants.
  • Record (Java 14+) — a class whose whole purpose is to carry immutable data. One line gives you fields, constructor, accessors, equals, hashCode, and toString.
দুটি খুব সাধারণ type-এর জন্য Java আলাদা keyword দিয়েছে। Enum — নির্দিষ্ট, নামকরা কয়েকটি instance-এর সেট (DayOfWeek, PaymentMethod, OrderStatus), type-safe ও self-documenting। Record (Java 14+) — একটি immutable data-class যা এক লাইনে field, constructor, accessor, equals/hashCode/toString সব দিয়ে দেয়।

2. Enums — More Than Named Integers

A Java enum is actually a full class under the hood. Each constant is a singleton instance, and the enum can carry fields, a constructor, and methods — including abstract methods that each constant overrides.

Main.java
enum MobileOperator {
    GP("Grameenphone", "017"),
    ROBI("Robi",          "018"),
    BANGLALINK("Banglalink", "019"),
    TELETALK("Teletalk",   "015");

    private final String fullName;
    private final String prefix;

    MobileOperator(String fullName, String prefix) {
        this.fullName = fullName;
        this.prefix   = prefix;
    }

    public String fullName() { return fullName; }
    public String prefix()   { return prefix;   }
}

class Main {
    public static void main(String[] args) {
        for (MobileOperator op : MobileOperator.values()) {
            System.out.println(op.fullName() + " → prefix " + op.prefix());
        }
    }
}
EnumSet & EnumMap are ultra-fast specialised collections for enum keys/values — internally just bit-sets or arrays. Always prefer them to HashSet<MobileOperator> when the keys are enum constants.
EnumSet ও EnumMap — enum-এর জন্য অনুকূলিত। Internally bit-set বা array ব্যবহার করে, তাই HashSet/HashMap-এর চেয়ে দ্রুত ও কম মেমোরি।

3. Records — One Line Replaces Forty

Before Java 14 an immutable "data" class needed private final fields, a constructor, getters, equals, hashCode, toString — easily 40 lines for three fields. A record gives you all of that, correctly implemented, in one line.

Main.java
record Point(int x, int y) {}

record Student(String name, double cgpa) {
    // Compact constructor — validate before fields are assigned
    Student {
        if (cgpa < 0 || cgpa > 4)
            throw new IllegalArgumentException("CGPA out of range");
    }
}

class Main {
    public static void main(String[] args) {
        Point p = new Point(2, 3);
        System.out.println(p);                // Point[x=2, y=3] — auto toString
        System.out.println(p.x() + "," + p.y()); // accessors are x()/y(), not getX()/getY()

        Student s = new Student("Maya", 3.8);
        System.out.println(s);                // Student[name=Maya, cgpa=3.8]

        System.out.println(p.equals(new Point(2, 3))); // true — value equality
    }
}
Record-এর প্রতিটি component (field) automatically private final হয়, নামের সাথে একই accessor method থাকে (x(), y())। Compact constructor দিয়ে validation করা যায়। equals, hashCode, toString compiler নিজেই সঠিকভাবে generate করে — value-based equality।

4. When to Use a Record (and When Not To)

Records shine for transparent data carriers — objects whose identity is their data: DTOs, API request/response shapes, cache keys, coordinates, tuples. Do not pick a record if you need mutable state, an inheritance hierarchy beyond Object, or fields that are conceptually hidden.

✅ Record fits

  • Immutable DTO / value object
  • Cache keys (free correct equals/hashCode)
  • Tuples: Pair<A,B>, Triple<A,B,C>
  • Request/response shapes for REST APIs

⚠️ Use a regular class

  • State mutates over time (accounts, sessions)
  • You need to hide internal representation
  • You need to extend another class
  • Complex invariants across multiple methods

5. Enums + switch Expressions

Enums compose beautifully with modern switch expressions — every case returns a value, and the compiler insists the switch is exhaustive. Add a new constant and the compiler hunts down every switch that needs updating.

Main.java
enum OrderStatus { NEW, PACKED, SHIPPED, DELIVERED, CANCELLED }

class Main {
    static String describe(OrderStatus s) {
        return switch (s) {
            case NEW        -> "Just placed";
            case PACKED     -> "Ready to ship";
            case SHIPPED    -> "On the way";
            case DELIVERED  -> "Arrived";
            case CANCELLED  -> "Cancelled";
        };
    }
    public static void main(String[] args) {
        System.out.println(describe(OrderStatus.SHIPPED));
    }
}

6. Vocabulary (শব্দভাণ্ডার)

TermMeaningবাংলায়
enumA fixed, named set of class instances.নির্দিষ্ট, নামকরা কয়েকটি instance।
values()Auto-generated array of all enum constants.সব enum constant-এর auto array।
EnumSetBit-set optimised set for enum keys.Enum-এর জন্য bit-set optimised set।
EnumMapArray-backed map with enum keys.Enum key-যুক্ত array-backed map।
recordTransparent immutable data class (Java 14+).Transparent immutable data class (Java 14+)।
ComponentRecord's data field; accessor has the same name.Record-এর ডেটা field; accessor-ও একই নাম।
Compact constructorRecord constructor without parameter list; for validation.Parameter list ছাড়া record constructor; validation-এর জন্য।

7. Practice Problems

  1. Declare an enum Currency with BDT, USD, EUR and a double rateToBdt field. Convert 100 USD to BDT using a method.
    Currency enum (BDT, USD, EUR) বানান — প্রতিটির rateToBdt field থাকবে। 100 USD কে BDT-তে রূপান্তর দেখান।
    ✨ Show Answer
    Main.java
    enum Currency {
        BDT(1.0), USD(118.0), EUR(128.0);
        final double rateToBdt;
        Currency(double r) { rateToBdt = r; }
        double toBdt(double amount) { return amount * rateToBdt; }
    }
    class Main {
        public static void main(String[] args) {
            System.out.println("100 USD = " + Currency.USD.toBdt(100) + " BDT");
        }
    }
  2. Define record Movie(String title, int year). Create two identical movies and print whether equals returns true.
    record Movie(String title, int year) বানান। দুটি একই movie তৈরি করুন ও equals true কিনা প্রিন্ট করুন।
    ✨ Show Answer
    Main.java
    record Movie(String title, int year) {}
    class Main {
        public static void main(String[] args) {
            Movie a = new Movie("Matir Moina", 2002);
            Movie b = new Movie("Matir Moina", 2002);
            System.out.println(a.equals(b));
        }
    }
  3. List three things Java generates for you when you declare a record.
    Record ঘোষণা করলে Java কী কী auto-generate করে — তিনটি বলুন।
    ✨ Show Answer

    Answer:

    • A canonical constructor matching the header, and a private final field for each component.
    • An accessor method per component (same name as the component, e.g. x()).
    • Correct value-based equals, hashCode, and a readable toString.

    Canonical constructor ও private final field; প্রতিটি component-এর accessor; সঠিক equals/hashCode/toString।

  4. Write an enum TrafficLight with an abstract method action(), overridden per constant to print what to do.
    TrafficLight enum বানান — abstract action() method, প্রতিটি constant-এ override করে কী করতে হবে print করবে।
    ✨ Show Answer
    Main.java
    enum TrafficLight {
        RED    { void action() { System.out.println("Stop"); } },
        YELLOW { void action() { System.out.println("Slow"); } },
        GREEN  { void action() { System.out.println("Go");   } };
        abstract void action();
    }
    class Main {
        public static void main(String[] args) {
            for (TrafficLight l : TrafficLight.values()) l.action();
        }
    }
  5. Why is a record always a poor replacement for a JavaBean-style mutable class? Two sentences.
    দুই বাক্যে — mutable JavaBean-এর বদলে record ব্যবহার কেন উপযুক্ত নয়?
    ✨ Show Answer

    Answer: A record is immutable by design — every component becomes a private final field and no setters are generated. If you need state that evolves over the object's life, you need a regular class with setters or explicit update methods.

    Record সবসময় immutable — field private final, setter নেই। State-কে সময়ের সাথে বদলাতে হলে সাধারণ class + setter দরকার।

Summary — Module 17

An enum is a first-class type for a fixed set of instances — it can carry fields, methods, and even per-constant behaviour, and it pairs perfectly with exhaustive switch expressions. A record (Java 14+) is a transparent, immutable carrier of data: one line of declaration gives you the fields, the constructor, accessors, and correct equals, hashCode, and toString. Use enums where "it's one of these"; use records for "it's just this data."

Enum নির্দিষ্ট কিছু instance-এর type — field, method, এমনকি per-constant আচরণও রাখতে পারে, এবং exhaustive switch-এ দারুণ মানিয়ে যায়। Record (Java 14+) transparent immutable ডেটা carrier — এক লাইনে field, constructor, accessor, equals/hashCode/toString পাওয়া যায়। "এটি কয়েকটির একটি" হলে enum, "এটি শুধু একগুচ্ছ ডেটা" হলে record।

Next Module → Nested, Inner ও Anonymous Class।