
Java 16 introduced Records, a new way to create immutable data classes with minimal boilerplate. They are perfect for storing data and replacing POJOs (Plain Old Java Objects) that require a lot of code for simple tasks.
1. What Are Records?
✅ Records are immutable data classes.
✅ Automatically generate equals()
, hashCode()
, and toString()
.
✅ Eliminate boilerplate code for simple objects.
2. How to Define a Record?
📌 Syntax of a Record
record Person(String name, int age) { }
✔ This automatically creates:
- Private final fields (
name
,age
) - A constructor
- Getters (
name()
andage()
) toString()
,equals()
, andhashCode()
methods
3. Example: Using a Record Instead of a Class
🔴 Traditional Java Class (Before Java 16)
public class Person {
private final String name;
private final int age;
public Person(String name, int age) { // Constructor
this.name = name;
this.age = age;
}
public String getName() { return name; } // Getter
public int getAge() { return age; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
🔴 Total Lines: ~15
🟢 Java 16+ Record (Same Functionality in 1 Line!)
record Person(String name, int age) { }
✔ Automatically generates everything needed!
✔ Cleaner and easier to maintain.
4. Records Provide Automatic Methods
📌 Example: Using a Record in Java 16+
public class Main {
public static void main(String[] args) {
Person p = new Person("Alice", 25);
System.out.println(p.name()); // ✅ Getter
System.out.println(p.age()); // ✅ Getter
System.out.println(p); // ✅ Auto-generated toString()
}
}
✅ Output:
Alice
25
Person[name=Alice, age=25]
✔ No need to manually write getName()
, getAge()
, or toString()
.
5. Records Are Immutable
🚨 You cannot modify record fields after creation!
📌 Example: Record Fields Are final
record Car(String model, int year) { }
public class Main {
public static void main(String[] args) {
Car car = new Car("Tesla", 2022);
car.year = 2023; // ❌ ERROR: Cannot modify a record field!
}
}
✅ Compiler Error:
error: cannot assign a value to final variable 'year'
✔ Records are immutable by default!
6. Adding Custom Methods to a Record
📌 Example: Adding a Custom Method
record Rectangle(double width, double height) {
double area() { // ✅ Custom method
return width * height;
}
}
✔ Records can have methods, but fields remain immutable!
7. When to Use Records?
🚀 Use record
when:
✔ You need an immutable data holder.
✔ You want auto-generated constructors, getters, and toString()
.
✔ You are working with DTOs (Data Transfer Objects), API responses, or simple models.
🚨 Do NOT use record
when:
❌ You need mutable objects (Use a normal class instead).
❌ You need inheritance (Records cannot extend other classes).
8. Comparison: Traditional Class vs. Record
Feature | Traditional Class | Java 16+ Record |
---|---|---|
Lines of Code | 🔴 15+ lines | 🟢 1 line |
Getters Required? | ✅ Yes (getName() , getAge() ) | ❌ No (name() , age() ) |
toString() Required? | ✅ Yes | ❌ No (Auto-generated) |
Immutability | ❌ Optional | ✅ Always Immutable |
Lesson Reflection
- How do Records simplify Java development compared to traditional classes?
- Why are Records immutable by default?
- When should you use a Record instead of a regular class?
Answers to Reflection Questions on Java 16+ Records (record
)
1️⃣ How do Records simplify Java development compared to traditional classes?
✅ Records eliminate boilerplate code
- No need to manually write getters, constructors,
toString()
,equals()
, orhashCode()
. - This makes code cleaner, more readable, and easier to maintain.
📌 Example: Traditional Class vs. Record
🔴 Before Java 16 (Verbose Code)
public class Person {
private final String name;
private final int age;
public Person(String name, int age) { // Constructor
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
}
🟢 Java 16+ Record (Same Functionality in 1 Line!)
record Person(String name, int age) { }
✔ Less code, same result!
2️⃣ Why are Records immutable by default?
✅ Records are meant to be simple, read-only data holders.
✅ Immutable objects are safer, prevent unintended modifications, and work well in multi-threaded applications.
📌 Example: Trying to Modify a Record Field
record Car(String model, int year) { }
public class Main {
public static void main(String[] args) {
Car car = new Car("Tesla", 2022);
car.year = 2023; // ❌ ERROR: Cannot modify a record field!
}
}
🚨 Compiler Error:
error: cannot assign a value to final variable 'year'
✔ Since fields are final
, records cannot be modified after creation.
3️⃣ When should you use a Record instead of a regular class?
🚀 Use a record
when:
✔ You need an immutable data holder.
✔ You want automatic getters and methods (toString()
, equals()
, etc.).
✔ You are working with DTOs (Data Transfer Objects), API responses, or simple models.
🚨 Do NOT use a record
when:
❌ You need mutable objects (Use a normal class instead).
❌ You need inheritance (Records cannot extend other classes).
📌 Example: When to Use a Record (Good Use Case)
record User(String username, String email) { }
✔ Perfect for API responses, where data should not change.
📌 Example: When NOT to Use a Record (Bad Use Case)
record BankAccount(String accountNumber, double balance) {
void deposit(double amount) {
balance += amount; // ❌ ERROR: Cannot modify record field!
}
}
🚨 Records cannot have mutable fields, so BankAccount
should be a regular class.
🔍 Key Takeaways
✔ Records simplify Java development by reducing boilerplate code.
✔ They are immutable by default, making them safer and more reliable.
✔ Use Records for immutable data structures like DTOs and API responses.
Making POJOs Simpler: New Ways to Reduce Boilerplate Code
While Records (record
) simplify immutable data classes, Java does not provide a built-in solution for mutable POJOs with get()
and set()
methods. However, there are modern approaches that can reduce boilerplate code in traditional JavaBeans (POJOs).
1️⃣ Lombok – The Most Popular Way to Reduce POJO Boilerplate
Lombok is a Java library that automatically generates get()
, set()
, toString()
, equals()
, and hashCode()
methods using annotations.
📌 Example: Simplifying a POJO with Lombok
import lombok.Data;
@Data // Generates getters, setters, toString(), equals(), and hashCode()
public class Person {
private String name;
private int age;
}
✅ Equivalent to this manually written Java class:
public class Person {
private String name;
private int age;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + "}";
}
@Override
public boolean equals(Object o) { /* Auto-generated */ }
@Override
public int hashCode() { /* Auto-generated */ }
}
✔ Lombok reduces POJO boilerplate from 50+ lines to just 5!
✔ Requires Lombok dependency (Maven/Gradle).
📌 Lombok Dependency for Maven
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
2️⃣ Java Records (record
) – Best for Immutable POJOs
If your class doesn’t need setters, you can use Java 16+ Records instead.
📌 Example: Replacing POJOs with a Record
record Person(String name, int age) { }
✔ Automatically generates getters, toString()
, equals()
, and hashCode()
.
✔ Immutable by default (no set()
methods).
🚨 Use Records only if you don’t need mutable fields!
3️⃣ Java 21: New value
Keyword (Experimental – Future Feature)
In Java 21+, the value
keyword (preview feature) is being introduced for lightweight, immutable data classes.
📌 Future Example: Using value
Classes (Java 21+)
value class Person {
String name;
int age;
}
🚀 This is still an experimental feature, but it may provide a built-in way to reduce POJO boilerplate without Lombok.
🔍 Summary: Best Approach for Your Use Case
Use Case | Best Approach | Why? |
---|---|---|
Immutable POJOs (No set() ) | ✅ record (Java 16+) | No setters, less boilerplate |
Mutable POJOs (With set() ) | ✅ Lombok @Data | Auto-generates getters & setters |
Future-Proof Lightweight Classes | ✅ Java 21+ value class (Experimental) | Will reduce POJO boilerplate further |
🚀 Final Thoughts
✔ Use Lombok (@Data
) if you need setters and mutable objects.
✔ Use record
(Java 16+) for immutable data classes.
✔ Java 21+ may introduce a value
keyword to simplify POJOs further.
The next Java 17+ feature: Pattern Matching in switch
Statements 😊🚀