"If a worker wants to do his job well, he must first sharpen his tools." - Confucius, "The Analects of Confucius. Lu Linggong"
Front page > Programming > Records vs Classes in Java

Records vs Classes in Java

Published on 2024-11-02
Browse:525

Records vs Clases en Java

If you already know records in Java, you may find its use very similar to that of classes, but there are important differences that must be taken into consideration. In this article we are going to see the differences between records and classes in Java. If you still don't know records I recommend reading my post Records in Java: what they are and how to use them.

Immutability

An immutable object is one whose attributes cannot be modified once the object has been created. In the case of records, these are immutable, that is, once an object of type record has been created, its attributes cannot be modified. On the other hand, a class may or may not be immutable, depending on how it is implemented. This part ensures the integrity of the data and prevents it from being accidentally modified.

Purpose

Classes are commonly written simply to store data, such as those from a database query, or the data from a form. In many cases, this data is immutable, since the validity of the data needs to be ensured without using synchronization. To achieve this, a class is written with the following elements:

  • Private attributes for each field.
  • Getters for each field.
  • A constructor that initializes all fields.
  • An equals method that compares objects for equality.
  • A hashCode method that generates a hash code based on the fields.
  • A toString method that generates a string representation of the fields.

For example, if you have a Person class with two attributes name and lastName, you could write it as follows:

public class Person {

    private final String name;
    private final String lastName;

    public Person(String name, String lastName) {
        this.name = name;
        this.lastName = lastName;
    }

    public String getName() {
        return name;
    }

    public String getLastName() {
        return lastName;
    }

    @Override
    public String toString() {
        return "Person{"   "name='"   name   '\''  
                ", lastName='"   lastName   '\''  
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Person person)) return false;
        return Objects.equals(getName(), person.getName()) && Objects.equals(getLastName(), person.getLastName());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getName(), getLastName());
    }
}

This is a solution to the task, but it is a lot of code for what is actually needed. If the class had more attributes, it would be an even longer code to write, even if done with the help of an IDE or a plugin like GitHub Copilot. A better solution would be to declare our class as a data-class, that is, a class that only stores data, and does not have to have a specific behavior, and this is where records come in.

In this way the Person class could be rewritten as a record as follows:

public record Person(String name, String lastName) { }

This automatically generates the equals, hashCode, and toString methods, as well as getter methods for each of the attributes.

What are the differences between a Record and a Class?

  • Immmutability: records are immutable, that is, once an object of type record has been created, its attributes cannot be modified. Instead, a class may or may not be immutable, depending on how it was implemented.
  • Generated methods: The records automatically generate the equals, hashCode and toString methods, as well as the getter methods for each of the attributes. However, in classes, these methods must be implemented manually or with the help of an IDE.
  • Use in OOP: records cannot inherit from other classes, nor be extended by other classes, but they can implement interfaces. On the other hand, classes can inherit from others, be extended, and in general are ideal for covering the concepts of Object-Oriented Programming.
  • Syntax: The syntax of a record is simpler than that of a class, since it can be defined in a single line, while a class requires several lines of code.
  • Purpose: The records are a structure that resembles a DTO (Data Transfer Object), that is, a class that helps model immutable data, for its part a class is a more general structure that can have behavior and state.

When to use a Record and when to use a Class?

If what is required is an immutable data structure to store data and no modifications to the attributes need to be made (it is simply seen as an object to carry information). On the other hand, if you need a more general structure that has unique logic and specific methods, an approach to an object-oriented paradigm, applying design patterns, or working with JPA or Hibernate, etc., then you should use a class .

Extra: Record with mutable attributes

Let's consider the following example, there are two records Product with the attributes name and price, and Cart with a single attribute products of type ArrayList and some methods to obtain the number of products and the total of the cart.

package org.jordi.example;

public record Product(String name, double price) { }
package org.jordi.example;

import java.util.ArrayList;
import java.util.List;

public record Cart(List products) {

    public Cart() {
        this(new ArrayList());
    }

    public int getQuantity() {
        return this.products.size();
    }

    public double getTotal() {
        return this.products.stream().mapToDouble(Product::price).sum();
    }
}

The issue in this case is that each of the record is immutable by itself, but in the case of the record Cart by having an attribute of type ArrayList and since by nature an ArrayList is mutable, you can modify the content of the list once the record Cart is instantiated.

package org.jordi.example;

public class Main {
    public static void main(String[] args) {
        Product water = new Product("Water", 15);
        Product milk = new Product("Milk", 22);

        Cart cart = new Cart();
        cart.products().add(water);
        cart.products().add(milk);
        System.out.println("Price: "   cart.getTotal());

        cart.products().clear();
        System.out.println("Quantity: "   cart.getQuantity());
        System.out.println("Price: "   cart.getTotal());
    }
}

The code above compiles without problems, since only the content of the list is being modified, but the products attribute itself is not being modified. This is just an example for a particular case, which is probably not necessary, but it is good to know that this can be done.

Release Statement This article is reproduced at: https://dev.to/asjordi/records-vs-clases-en-java-1bb6?1 If there is any infringement, please contact [email protected] to delete it
Latest tutorial More>

Disclaimer: All resources provided are partly from the Internet. If there is any infringement of your copyright or other rights and interests, please explain the detailed reasons and provide proof of copyright or rights and interests and then send it to the email: [email protected] We will handle it for you as soon as possible.

Copyright© 2022 湘ICP备2022001581号-3