Java Records vs Traditional Classes: When and how to use Java Records

Published on 2024-10-09, by Javed Shaikh

Subscribe for new article
*No spam. unsubscribe at anytime

Java introduced records in version 14 as a preview feature and made them a standard feature in Java 16. Records provide a concise way to create data carrier classes, which are primarily used to hold data without much behavior. In this blog post, we’ll explore the differences between records and traditional classes, and when to use each.


What are Java Records?

Records are a special kind of class in Java that are designed to hold immutable data. They automatically provide implementations for common methods like equals(), hashCode(), and toString(), which makes them ideal for data transfer objects (DTOs) or simple data carriers.

Defining a Record

Here’s how you can define a record in Java:

java
1public record Person(String name, int age) { 2}

Using a Record

You can create an instance of a record just like a traditional class:

java
1public class Main { 2 public static void main(String[] args) { 3 Person person = new Person("Alice", 30); 4 System.out.println(person); // Output: Person[name=Alice, age=30] 5 } 6}

Traditional Classes

Traditional classes in Java can be more flexible, allowing for mutable state, complex behavior, and inheritance. However, they require more boilerplate code to achieve similar functionality as records.

Defining a Traditional Class

Here’s an example of a traditional class:

java
1public class Person { 2 private final String name; 3 private final int age; 4 5 public Person(String name, int age) { 6 this.name = name; 7 this.age = age; 8 } 9 10 public String getName() { 11 return name; 12 } 13 14 public int getAge() { 15 return age; 16 } 17 18 @Override 19 public String toString() { 20 return "Person{name='" + name + "', age=" + age + "}"; 21 } 22 23 @Override 24 public boolean equals(Object o) { 25 if (this == o) return true; 26 if (!(o instanceof Person)) return false; 27 Person person = (Person) o; 28 return age == person.age && name.equals(person.name); 29 } 30 31 @Override 32 public int hashCode() { 33 return Objects.hash(name, age); 34 } 35}

Using a Traditional Class

You can create an instance of the traditional class similarly:

java
1public class Main { 2 public static void main(String[] args) { 3 Person person = new Person("Alice", 30); 4 System.out.println(person); // Output: Person{name='Alice', age=30} 5 } 6}

Key Differences Between Records and Traditional Classes

Boilerplate Code: Records significantly reduce boilerplate code. With records, we don’t need to write getters, toString(), equals(), or hashCode() methods.

Immutability: Records are inherently immutable. Once created, we cannot change their fields.

Inheritance: Records cannot extend other classes (they implicitly extend java.lang.Record), while traditional classes can extend other classes and implement interfaces.

Use Cases: We should use records when we need simple data carriers with no additional behavior. Use traditional classes when there is need for more complex behavior, mutable state, or inheritance.

When to Use Each

Use Records:

  • When we need a simple data structure.
  • When we want to reduce boilerplate code.
  • When immutability is a requirement.

Use Traditional Classes:

  • When we need mutable objects.
  • When the requirement is for complex behavior or methods.
  • When we need to implement inheritance or interfaces.
About the Author

I am a Backend System Engineer at a credit card company, specializing in C/C++ and assembler on IBM's TPF OS. I have a passion for web development and enjoy working with Node.js and Python in my free time.

Connect with author

Related articles ...

How to optimize Spring Boot Application Performance with just few steps

Spring Boot applications are known for their ease of development and rapid deployment, but as your application scales, performance optimization becomes crucial.

2024-05-08

Spring Boot Actuator for Performance Monitoring

Spring Boot Actuator is a crucial tool for monitoring and managing Spring Boot applications in production. It provides ready-to-use endpoints that help track application health, metrics, and performance.

2024-02-05

Building a TCP Server with Reactor Netty and Spring Boot: A Step-by-Step Guide

When it comes to building high-performance, scalable TCP servers, the combination of Reactor Netty and Spring Boot offers a powerful solution. Reactor Netty provides a non-blocking and reactive approach to network programming, while Spring Boot simplifies the setup and configuration process

2024-01-02

Optimizing Memory Configuration in Java Applications

Understanding how to optimize memory configuration can dramatically improve your application's throughput, reduce latency, and prevent dreaded OutOfMemoryError exceptions

2024-07-17