Skip to content
Laviyx Learn

Try

Java course menu

Java Records and Enums: Data Classes and Fixed Sets of Constants

Learn Java records (Java 16+): compact immutable data classes with auto-generated constructors, accessors, equals, hashCode and toString, compact constructors for validation; and enums: constants, values(), valueOf, switch, fields, constructors and methods.

Intermediate11 min readUpdated
On this page

Two special kinds of class save a lot of code: records, for classes that simply hold data, and enums, for a fixed set of named values.

Records: data classes in one line#

A plain data class needs a constructor, getters, equals, hashCode and toString, which is dozens of lines of boilerplate. A record (Java 16+) generates all of them:

Java
record Point(int x, int y) {}

public class Main {
    public static void main(String[] args) {
        Point p = new Point(3, 4);
        Point q = new Point(3, 4);

        System.out.println(p);
        System.out.println(p.x() + " " + p.y());
        System.out.println(p.equals(q) + " " + (p == q));
        System.out.println(p.hashCode() == q.hashCode());
    }
}
Output
Point[x=3, y=4]
3 4
true false
true

From record Point(int x, int y), Java generates:

  • private final fields x and y;
  • a constructor taking (int x, int y);
  • accessor methods x() and y() (no get prefix);
  • equals and hashCode that compare the values;
  • a readable toString.

Records are immutable: there are no setters, and the fields are final.

Validation with a compact constructor#

To check arguments, add a compact constructor, which has no parameter list and runs before the fields are assigned:

Java
record Percentage(double value) {
    Percentage {
        if (value < 0 || value > 100) {
            throw new IllegalArgumentException("must be 0-100: " + value);
        }
    }

    double asFraction() {          // records can have methods
        return value / 100;
    }
}

public class Main {
    public static void main(String[] args) {
        Percentage p = new Percentage(45);
        System.out.println(p + " = " + p.asFraction());
        try {
            new Percentage(140);
        } catch (IllegalArgumentException e) {
            System.out.println("Rejected: " + e.getMessage());
        }
    }
}
Output
Percentage[value=45.0] = 0.45
Rejected: must be 0-100: 140.0

Records in collections#

Because equals and hashCode are value-based, records work perfectly in sets and as map keys:

Java
import java.util.HashSet;
import java.util.List;
import java.util.Set;

record Student(String name, int marks) {}

public class Main {
    public static void main(String[] args) {
        List<Student> students = List.of(
                new Student("Asha", 92), new Student("Ravi", 85), new Student("Asha", 92));

        Set<Student> unique = new HashSet<>(students);
        System.out.println(unique.size());

        int total = 0;
        for (Student s : students) total += s.marks();
        System.out.println(total);
    }
}
Output
2
269

Use records for values that are defined by their data: points, money amounts, coordinates, API responses, and results with several parts.

Records cannot extend other classes (they implicitly extend java.lang.Record), but they can implement interfaces.

Enums: a fixed set of named values#

An enum defines a type with a fixed list of constants, such as days of the week or order statuses:

Java
enum OrderStatus { PENDING, SHIPPED, DELIVERED, CANCELLED }

public class Main {
    public static void main(String[] args) {
        OrderStatus status = OrderStatus.SHIPPED;

        if (status == OrderStatus.SHIPPED) {
            System.out.println("On its way!");
        }

        System.out.println(status + " " + status.ordinal());
        for (OrderStatus s : OrderStatus.values()) {
            System.out.print(s + " ");
        }
        System.out.println();
        System.out.println(OrderStatus.valueOf("DELIVERED"));
    }
}
Output
On its way!
SHIPPED 1
PENDING SHIPPED DELIVERED CANCELLED 
DELIVERED
  • Enum constants are written in UPPER_CASE.
  • Compare enum values with == (each constant exists exactly once).
  • values() returns all constants; valueOf("NAME") converts text (throws IllegalArgumentException for unknown names); ordinal() gives the position.

Using OrderStatus.SHIPPED instead of a magic number like 1 or a string like "shipped" makes code self-explanatory, and the compiler rejects invalid values and typos.

Enums with fields and methods#

Enums are full classes: constants can carry data, and the enum can have methods:

Java
enum Planet {
    MERCURY(3.303e23, 2.4397e6),
    EARTH(5.976e24, 6.37814e6),
    JUPITER(1.9e27, 7.1492e7);

    private final double mass;     // kg
    private final double radius;   // m

    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }

    double surfaceGravity() {
        return 6.67300e-11 * mass / (radius * radius);
    }
}

public class Main {
    public static void main(String[] args) {
        for (Planet p : Planet.values()) {
            System.out.printf("%-8s %.2f m/s2%n", p, p.surfaceGravity());
        }
    }
}
Output
MERCURY  3.70 m/s2
EARTH    9.80 m/s2
JUPITER  24.81 m/s2

Enums and switch#

A switch expression over an enum that covers every constant needs no default, and the compiler warns you if a new constant is not handled:

Java
enum Level { BEGINNER, INTERMEDIATE, ADVANCED }

public class Main {
    static int hoursPerWeek(Level level) {
        return switch (level) {
            case BEGINNER -> 3;
            case INTERMEDIATE -> 5;
            case ADVANCED -> 8;
        };
    }

    public static void main(String[] args) {
        System.out.println(hoursPerWeek(Level.INTERMEDIATE));
    }
}
Output
5

EnumMap and EnumSet are specialized, very fast collections keyed by enum constants.

Common mistakes#

Practice#

Practice exercise

Define enum Size { SMALL, MEDIUM, LARGE } with a price for each (100, 150, 200), and record Order(String drink, Size size, int quantity) with a method total(). Print an order of 3 MEDIUM coffees and its total.

Show solution
Java
enum Size {
    SMALL(100), MEDIUM(150), LARGE(200);

    private final int price;

    Size(int price) {
        this.price = price;
    }

    int price() {
        return price;
    }
}

record Order(String drink, Size size, int quantity) {
    int total() {
        return size.price() * quantity;
    }
}

public class Cafe {
    public static void main(String[] args) {
        Order order = new Order("coffee", Size.MEDIUM, 3);
        System.out.println(order);
        System.out.println("Total: " + order.total());
    }
}
Output
Order[drink=coffee, size=MEDIUM, quantity=3]
Total: 450

Key takeaway#

Finished this lesson?