"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Registros versus classes em Java

Registros versus classes em Java

Publicado em 2024-11-02
Navegar:398

Records vs Clases en Java

Se você já conhece registros em Java, pode achar seu uso muito semelhante ao de classes, mas existem diferenças importantes que devem ser levadas em consideração. Neste artigo veremos as diferenças entre records e classes em Java. Se você ainda não conhece registros recomendo a leitura do meu post Registros em Java: o que são e como utilizá-los.

Imutabilidade

Um objeto imutável é aquele cujos atributos não podem ser modificados depois que o objeto foi criado. No caso dos records, estes são imutáveis, ou seja, uma vez criado um objeto do tipo record seus atributos não podem ser modificados. Por outro lado, uma classe pode ou não ser imutável, dependendo de como é implementada. Esta parte garante a integridade dos dados e evita que sejam modificados acidentalmente.

Propósito

As classes geralmente são escritas simplesmente para armazenar dados, como aqueles de uma consulta de banco de dados ou dados de um formulário. Em muitos casos, esses dados são imutáveis, uma vez que a validade dos dados precisa ser garantida sem o uso de sincronização. Para conseguir isso, uma classe é escrita com os seguintes elementos:

  • Atributos privados para cada campo.
  • Getters para cada campo.
  • Um construtor que inicializa todos os campos.
  • Um método equals que compara objetos quanto à igualdade.
  • Um método hashCode que gera um código hash baseado nos campos.
  • Um método toString que gera uma representação de string dos campos.

Por exemplo, se você tiver uma classe Person com dois atributos nome e sobrenome, você poderia escrevê-la da seguinte forma:

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());
    }
}

Esta é uma solução para a tarefa, mas é muito código para o que é realmente necessário. Se a classe tivesse mais atributos, seria um código ainda mais longo para escrever, mesmo que feito com a ajuda de um IDE ou de um plugin como o GitHub Copilot. Uma solução melhor seria declarar nossa classe como uma classe de dados, ou seja, uma classe que apenas armazena dados, e não precisa ter um comportamento específico, e é aí que entram os registros.

Desta forma a classe Person poderia ser reescrita como um record da seguinte forma:

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

Isso gera automaticamente os métodos equals, hashCode e toString, bem como métodos getter para cada um dos atributos.

Quais são as diferenças entre um registro e uma classe?

  • Imutabilidade: registros são imutáveis, ou seja, uma vez criado um objeto do tipo record seus atributos não podem ser modificados. Em vez disso, uma classe pode ou não ser imutável, dependendo de como foi implementada.
  • Métodos gerados: Os records geram automaticamente os métodos equals, hashCode e toString, bem como os métodos getter para cada um dos atributos. Porém, nas aulas, esses métodos devem ser implementados manualmente ou com a ajuda de um IDE.
  • Uso em OOP: registros não podem herdar de outras classes, nem ser estendidos por outras classes, mas podem implementar interfaces. Por outro lado, as classes podem herdar de outras, ser estendidas e em geral são ideais para abranger os conceitos de Programação Orientada a Objetos.
  • Sintaxe: A sintaxe de um registro é mais simples que a de uma classe, pois pode ser definida em uma única linha, enquanto uma classe requer várias linhas de código.
  • Objetivo: Os registros são uma estrutura que lembra um DTO (Data Transfer Object), ou seja, uma classe que ajuda a modelar dados imutáveis, por sua vez uma classe é uma estrutura mais geral que pode ter comportamento e estado.

Quando usar um Registro e quando usar uma Classe?

Se o que é necessário é uma estrutura de dados imutável para armazenar dados e nenhuma modificação nos atributos precisa ser feita (ela é simplesmente vista como um objeto para transportar informações). Por outro lado, se você precisa de uma estrutura mais geral que tenha lógica única e métodos específicos, uma abordagem para um paradigma orientado a objetos, aplicando padrões de design, ou trabalhando com JPA ou Hibernate, etc., então você deve usar uma classe.

Extra: Registro com atributos mutáveis

Vamos considerar o exemplo a seguir, existem dois registros Produto com os atributos nome e preço, e Carrinho com um único atributo produtos do tipo ArrayList e alguns métodos para obter a quantidade de produtos e o total do carrinho.

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();
    }
}

A questão neste caso é que cada um dos record é imutável por si só, mas no caso do registro Cart por ter um atributo do tipo ArrayList e já que por natureza um ArrayList é mutável , você pode modificar o conteúdo da lista assim que o registro Cart for instanciado.

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());
    }
}

O código acima compila sem problemas, pois apenas o conteúdo da lista está sendo modificado, mas o atributo de produtos em si não está sendo modificado. Este é apenas um exemplo para um caso particular, o que provavelmente não é necessário, mas é bom saber que isso pode ser feito.

Declaração de lançamento Este artigo está reproduzido em: https://dev.to/asjordi/records-vs-clases-en-java-1bb6?1 Se houver alguma infração, entre em contato com [email protected] para excluí-la
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3