Records
For decades, a simple Java class that just held a few values meant pages of boilerplate — fields, a constructor, getters, equals , hashCode , toString . Records (Java 16+) collapse all of that into a single line, giving you immutable, correct data classes for free.
Learn Records in our free Java course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Java course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
You should know classes, constructors, and fields , and have met equals and hashCode — records generate both for you, so seeing the manual version first makes the magic obvious.
💡 Analogy: Writing a data class the old way is like filling in a long form by hand — name field, address field, signature, witness — for every single document. A record is a pre-filled template: you state the fields once on the dotted line ( record Point(int x, int y) ) and the rest — constructor, accessors, equality, printing — is stamped in automatically. Less to write, nothing to get wrong.
The components you list in the parentheses are the record's whole identity. Two records are .equals() when their components are equal — value-based, not reference-based — which is exactly what you want for data.
A record declaration lists its components in parentheses. From that one line Java generates: private final fields, a canonical constructor, an accessor per component, and equals / hashCode / toString .
To appreciate records, look at what you'd otherwise hand-write — and have to keep in sync every time you add a field. A record does all of this, correctly, in one line.
Records aren't just dumb holders. A compact constructor lets you validate or normalise inputs — note it has no parameter list and no field assignments ; you only write the checks, and Java assigns the fields afterwards.
You can also add normal methods, derived values, static factory methods, and implement interfaces (including Comparable ). What you can't do: add extra instance fields or extend another class.
Records shine with the rest of modern Java. Because each component has a clean accessor, method references like Product::price plug straight into a Comparator . This is the combination you'll meet again in the checkpoint.
These lines declare a record with a compact constructor and use it. Put them in the right order.
Open the record header, open the compact constructor (no parameter list!), add the validation, close the constructor, close the record, then use it.
Predict the output before opening each answer.
Answer: true Coord[x=1, y=2] . Records get value-based equals for free, so two coords with the same components are equal, and the generated toString prints the component names and values.
Answer: No. A record component becomes a private final field with no setter, so u.name = "Bob" fails to compile ( cannot assign a value to final variable name , and the field isn't accessible anyway). Records are immutable — to "change" one, create a new instance.
Answer: C — m.cents() . The accessor is named after the component with no "get" prefix and is a method call, so m.getCents() doesn't exist and m.cents (the field) is private.
🎯 Your Turn #1 — Declare a record
Write a one-line Book record with the right components so the main method compiles.
🎯 Your Turn #2 — Validate with a compact constructor
Add a compact constructor that rejects a negative quantity.
🧩 Mini-Challenge — Contact book
Model contacts with a record, then sort and print them with aligned columns.
You can now declare records, know exactly what they generate, why they're immutable and value-based, how to validate with a compact constructor, and how to add your own methods. You've replaced pages of error-prone boilerplate with a single, correct line.
Next up: Regular Expressions — matching and extracting text patterns with Pattern and Matcher.
Practice quiz
Which does a record NOT generate automatically?
- A canonical constructor
- Accessor methods
- Setter methods
- equals, hashCode, and toString
Answer: Setter methods. Records are immutable, so they generate accessors but never setters.
For 'record Point(int x, int y) {}', how do you read x?
- p.getX()
- p.x
- p.x()
- p.getx()
Answer: p.x(). Accessors are named after the component with no 'get' prefix: p.x().
What does the generated toString() print for new Point(3, 4)?
- Point(3, 4)
The generated toString prints Point[x=3, y=4].
Are two records equal when their components are equal?
- No, equals is reference-based
- Yes — equals is value-based
- Only if the same instance
- Only for one component
Answer: Yes — equals is value-based. Records get value-based equals: same components means equal.
A record component becomes what kind of field?
- public mutable
- private final
- protected
- static
Answer: private final. Each component becomes a private final field — records are immutable.
What is a compact constructor used for?
- Adding setters
- Validating or normalising inputs without re-listing parameters
- Extending a class
- Adding new fields
Answer: Validating or normalising inputs without re-listing parameters. A compact constructor validates inputs; Java assigns the fields afterward.
Which can a record do?
- Extend another class
- Add extra mutable instance fields
- Implement an interface
- Have public non-final fields
Answer: Implement an interface. A record can implement interfaces but cannot extend a class or add extra instance fields.
Can you reassign a record component after construction, e.g. u.name = "Bob"?
- Yes
- No — the field is private final
- Only inside main
- Only with a setter
Answer: No — the field is private final. Components are private final with no setter, so reassignment fails to compile.
In which Java version did records become a final (non-preview) feature?
- Java 8
- Java 11
- Java 16
- Java 21
Answer: Java 16. Records were a preview in 14-15 and final from Java 16.
Why is a record's immutability described as 'shallow'?
- It only applies to ints
- A mutable component (like a List) can still have its contents changed
- Records can be reassigned
- Only the first field is final
Answer: A mutable component (like a List) can still have its contents changed. The reference can't change, but a mutable component's contents still can — prefer immutable components.