Records (Java 16+)
Part of the Object Oriented Programming section of Coddy's Java journey — lesson 51 of 87.
When creating simple data-carrying classes, you often write repetitive boilerplate code: private fields, a constructor, getters, toString(), equals(), and hashCode(). Java 16 introduced records to eliminate this tedium.
A record is a special class designed to hold immutable data. You declare it with the record keyword followed by the component list:
record Person(String name, int age) { }
// That single line automatically provides:
// - private final fields: name and age
// - a constructor: Person(String name, int age)
// - accessor methods: name() and age()
// - toString(), equals(), and hashCode()Using a record is straightforward:
Person p = new Person("Alice", 30);
System.out.println(p.name()); // Alice
System.out.println(p.age()); // 30
System.out.println(p); // Person[name=Alice, age=30]Notice that accessor methods don't use the get prefix—they're simply named after the fields. Records are implicitly final, so they cannot be extended. All fields are final too, making records inherently immutable.
You can add custom methods and override the auto-generated ones if needed. You can also add validation in a compact constructor:
record Person(String name, int age) {
public Person {
if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
}
}Records are perfect for DTOs, API responses, or any scenario where you need a simple, immutable data container without writing boilerplate code.
Challenge
EasyLet's build a movie ticket booking system that showcases the elegance of Java records. You'll see how records eliminate boilerplate code while still allowing you to add custom methods and validation.
You'll organize your code across three files:
Movie.java: Create a record representing a movie with three components:title(String),genre(String), anddurationMinutes(int). Add a custom method calledgetFormattedDuration()that returns the duration in a friendly format:[hours]h [minutes]m(for example, 142 minutes becomes2h 22m). Use integer division and modulo to calculate hours and remaining minutes.Ticket.java: Create a record representing a movie ticket with three components:movie(Movie),seatNumber(String), andprice(double). Add a compact constructor that validates the price—if the price is less than or equal to zero, throw anIllegalArgumentExceptionwith the messagePrice must be positive. Also add a custom method calledprintTicket()that returns a multi-line string:========== TICKET ========== Movie: [movie title] Genre: [movie genre] Duration: [formatted duration from movie] Seat: [seatNumber] Price: $[price] ============================Main.java: Bring your booking system together! You'll receive five inputs: movie title (String), genre (String), duration in minutes (int), seat number (String), and ticket price (double).Create a Movie record with the first three inputs, then create a Ticket record with the movie, seat number, and price. Print the result of calling
printTicket()on your ticket.
You will receive five inputs in order: movie title, genre, duration (minutes), seat number, and price.
Notice how much cleaner records are compared to traditional classes—no need to write constructors, getters, toString(), equals(), or hashCode(). The compact constructor lets you add validation without repeating field assignments, and you can still add custom methods when needed!
Cheat sheet
Java 16 introduced records to eliminate boilerplate code for simple data-carrying classes. A record is a special class designed to hold immutable data.
Declare a record with the record keyword followed by the component list:
record Person(String name, int age) { }This automatically provides:
- Private final fields
- A constructor
- Accessor methods (without
getprefix) toString(),equals(), andhashCode()
Using a record:
Person p = new Person("Alice", 30);
System.out.println(p.name()); // Alice
System.out.println(p.age()); // 30
System.out.println(p); // Person[name=Alice, age=30]Records are implicitly final and cannot be extended. All fields are final, making records inherently immutable.
Add validation using a compact constructor:
record Person(String name, int age) {
public Person {
if (age < 0) throw new IllegalArgumentException("Age cannot be negative");
}
}You can add custom methods to records:
record Person(String name, int age) {
public String getInfo() {
return name + " is " + age + " years old";
}
}Try it yourself
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Read inputs
String title = scanner.nextLine();
String genre = scanner.nextLine();
int durationMinutes = Integer.parseInt(scanner.nextLine());
String seatNumber = scanner.nextLine();
double price = Double.parseDouble(scanner.nextLine());
// TODO: Create a Movie record with title, genre, and durationMinutes
// TODO: Create a Ticket record with the movie, seatNumber, and price
// TODO: Print the ticket using printTicket() method
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe this KeywordMethodsFields (Attributes)Constructor MethodConstructor OverloadingRecap - Simple Calculator4Inheritance
Basic Inheritance (extends)The super KeywordMethod Overriding (@Override)Constructor ChainingThe Object ClassSingle & Multilevel InheritWhy No Multi Class InheritRecap - Employee Hierarchy7Special Methods & Object Class
toString() Methodequals() and hashCode()clone() MethodcompareTo() and ComparableComparator InterfaceRecap - Custom Sorting2Access Modifiers & Encapsulate
Access Levels OverviewGetter and Setter MethodsInformation HidingThe final KeywordRecap - Bank Account Manager5Polymorphism
Method Overloading BasicsMethod Overriding (Run-Time)Upcasting and DowncastingThe instanceof OperatorAbstract Classes and MethodsRecap - Shape Calculator8Advanced OOP Concepts
Composition vs InheritanceAggregation vs CompositionInner Nested & Anonymous ClassEnums and Enum MethodsRecords (Java 16+)Sealed Classes (Java 17+)3Class Props & Static Member
Instance vs Static VariablesStatic MethodsStatic BlocksConstants (static final)Recap - Counter & Utility6Interfaces & Abstract Classes
Introduction to InterfacesImplementing InterfacesMulti Interface ImplemenDefault & Static in InterfaceAbstract Classes vs InterfacesFunctional InterfacesRecap - Payment System