Java Intermediate: Objects, Collections and Errors
Enums and Records
In this lesson you will
- Define and use enums, including fields and methods
- Declare records and validate their data
- Combine enums and records with switch
Introduction
Two kinds of class come up constantly. One is a value that can only be one of a fixed set of options: a day of the week, a traffic light colour, an order status. The other is a plain bundle of data, like a point or a customer. Java has special, compact syntax for each: enums and records.
Enums
An enum defines a fixed set of constants.
Java
enum Day {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
public class Main {
public static void main(String[] args) {
Day today = Day.WEDNESDAY;
System.out.println(today);
System.out.println(today.ordinal());
System.out.println(Day.valueOf("FRIDAY"));
System.out.println(today == Day.WEDNESDAY);
for (Day d : Day.values()) {
System.out.print(d.name().charAt(0));
}
System.out.println();
}
}WEDNESDAY
2
FRIDAY
true
MTWTFSS- Constants are written in capitals, and used as
Day.WEDNESDAY. ordinal()is the position (starting at 0),values()lists all constants, andvalueOfconverts text to a constant.- Compare enums with
==. - A variable of type
Daycannot hold anything else, so typos like"Wednsday"become impossible.
Quick quiz
What is the advantage of an enum over using plain Strings for a status?
Enums with fields and methods
An enum is really a special class, so each constant can carry data and behaviour.
Java
enum Planet {
MERCURY(0.38),
EARTH(1.00),
MARS(0.38),
JUPITER(2.53);
private final double gravity;
Planet(double gravity) {
this.gravity = gravity;
}
double weightOf(double earthWeight) {
return earthWeight * gravity;
}
}
public class Main {
public static void main(String[] args) {
for (Planet p : Planet.values()) {
System.out.printf("%s: %.1f%n", p, p.weightOf(60));
}
}
}MERCURY: 22.8
EARTH: 60.0
MARS: 22.8
JUPITER: 151.8The constants are created with constructor arguments, and the list ends with a semicolon before the fields and methods.
Enums with switch
switch and enums work well together. In a switch expression over an enum, the compiler can check that you covered every constant.
Java
enum Light { RED, YELLOW, GREEN }
public class Main {
static String action(Light light) {
return switch (light) {
case RED -> "stop";
case YELLOW -> "get ready";
case GREEN -> "go";
};
}
public static void main(String[] args) {
for (Light l : Light.values()) {
System.out.println(l + ": " + action(l));
}
}
}RED: stop
YELLOW: get ready
GREEN: goIf someone adds FLASHING to the enum later, this code stops compiling until the new case is handled. That is a gift.
Records
A record (Java 16 and newer) is a short way to write an immutable data class. Without records, a simple Point needs fields, a constructor, getters, equals, hashCode and toString. A record writes all of that for you.
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));
System.out.println(p == q);
}
}Point[x=3, y=4]
7
true
falseYou get a constructor, accessor methods named after the components (p.x(), with no "get"), a readable toString, and an equals that compares the contents. Record fields cannot be changed after creation.
Validating and extending records
A compact constructor runs checks before the fields are set. Records can also have extra methods and static helpers.
Java
record Temperature(double celsius) {
Temperature {
if (celsius < -273.15) {
throw new IllegalArgumentException("below absolute zero");
}
}
double fahrenheit() {
return celsius * 9 / 5 + 32;
}
static Temperature ofFahrenheit(double f) {
return new Temperature((f - 32) * 5 / 9);
}
}
public class Main {
public static void main(String[] args) {
Temperature boiling = new Temperature(100);
System.out.println(boiling.fahrenheit());
System.out.println(Temperature.ofFahrenheit(212));
try {
new Temperature(-300);
} catch (IllegalArgumentException e) {
System.out.println("Invalid: " + e.getMessage());
}
}
}212.0
Temperature[celsius=100.0]
Invalid: below absolute zeroQuick quiz
What does a record give you automatically?
Putting them together
Records and enums combine naturally to model real data:
Java
import java.util.List;
enum Status { TODO, DOING, DONE }
record Task(String title, Status status) {}
public class Main {
public static void main(String[] args) {
List<Task> tasks = List.of(
new Task("Write report", Status.DOING),
new Task("Tidy desk", Status.TODO),
new Task("Pay bill", Status.DONE)
);
for (Task t : tasks) {
String icon = switch (t.status()) {
case TODO -> "[ ]";
case DOING -> "[~]";
case DONE -> "[x]";
};
System.out.println(icon + " " + t.title());
}
}
}[~] Write report
[ ] Tidy desk
[x] Pay billTry it yourself
On your computer, create an enum Size with SMALL, MEDIUM and LARGE, each with a price (such as 2.0, 3.0 and 4.0), and a record Order(String drink, Size size). Write a method that returns the price of an order, and print the total of three orders.
Summary
- An enum defines a fixed set of constants. It can have fields, constructors and methods, and works with
switch. - A record is a compact immutable data class with an automatic constructor, accessors,
equalsandtoString. - A compact constructor validates record data.
- Together they model real data clearly, and a switch over an enum is checked for completeness.
Lesson complete
+20 XP
Nice work. Keep going while it is fresh.
Sources and further reading