Java Records
In this page:
record RecordName(Type component1, Type component2) { }
RecordName object = new RecordName(value1, value2);
object.component1();
Introduction to Records
A Java record is a special, compact kind of class designed specifically to act as a simple, immutable data carrier. Declaring one automatically generates private final fields, a canonical constructor, accessor methods, and correct hashCode(), equals(), and toString() implementations, all without you writing that boilerplate by hand.
Example: Introduction to Records
// Define the class Main
public class Main {
// Define the record Point (an immutable data carrier)
record Point(int x, int y) {}
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Create a new Point object and store it in p
Point p = new Point(3, 4);
// Print a line to the console
System.out.println(p.x() + "," + p.y() + " " + p);
}
}
Login to try C/C++/Java/PHP code in the editor
Compact Constructors
You can add a compact constructor to a record to validate or normalize its data before it's stored, without needing to redeclare the record's parameter list in that constructor's signature. This is the idiomatic place to reject invalid input, such as throwing on a negative age.
Example: Compact Constructors
// Define the class Main
public class Main {
// Define the record Person (an immutable data carrier)
record Person(String name, int age) {
Person {
if (age < 0) throw new IllegalArgumentException("age cannot be negative");
}
}
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Create a new Person object and store it in p
Person p = new Person("Anya", 25);
// Print a line to the console
System.out.println(p);
}
}
Login to try C/C++/Java/PHP code in the editor
Custom Methods and Fields
You can define custom instance methods, static methods, and static fields inside a record just like an ordinary class. However, you cannot declare any additional instance fields beyond the ones already listed in the record's header, since that would break its guarantee of being a simple, fixed data shape.
Example: Custom Methods and Fields
// Define the class Main
public class Main {
// Define the record Circle (an immutable data carrier)
record Circle(double radius) {
static final double PI = 3.14159;
double area() {
// Send PI * radius * radius back to the caller
return PI * radius * radius;
}
}
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Create a new Circle object and store it in c
Circle c = new Circle(2);
// Print a line to the console
System.out.println(c.area());
}
}
Login to try C/C++/Java/PHP code in the editor
Implementing Interfaces
Records are implicitly final, meaning they can never extend any other class, since allowing subclassing would undermine their immutability guarantees. They can, however, implement any number of interfaces, which is how you give a record additional behavior or contracts.
Example: Implementing Interfaces
// Define the class Main
public class Main {
// Define the interface Shape
interface Shape {
double area();
}
// Define the record Square (an immutable data carrier)
record Square(double side) implements Shape {
public double area() { return side * side; }
}
// Program entry point: the JVM starts running here
public static void main(String[] args) {
// Create a new Square object and store it in s
Shape s = new Square(4);
// Print a line to the console
System.out.println(s.area());
}
}
Login to try C/C++/Java/PHP code in the editor
Nested and Local Records
You can declare a record nested inside another class, or even locally inside a single method's scope for a quick, throwaway data shape. Local records declared inside a method are implicitly static, so they can't capture the enclosing instance.
Example: Nested and Local Records
public class Main {
record Outer(int value) {
record Inner(String label) {} // nested record
}
public static void main(String[] args) {
record Local(int n) {} // local record, implicitly static
Local l = new Local(7);
System.out.println(l);
}
}
Login to try C/C++/Java/PHP code in the editor
- Trying to call a setter or change a record field, when all record components are final so a record cannot be modified after creation.
- Calling
p.getX(), when a record's accessor is named after the component, so it isp.x(). - Trying to make a record extend another class or declare extra instance fields, which is not allowed because records already extend
Recordand only have their components.
Chapter Quiz — Complete all 12 topics to unlock
0/12 topics done
Complete these topics first: