Classes Imutáveis no Java e Records
Tags: java, backend, backenddevelopment, webdev
Published: 2023-09-03 23:10:30

Classes imutáveis são aquelas cujas instâncias não podem ser modificadas durante toda a vida útil do objeto, como por exemplo a classe String.

Ter um objeto imutável garante que seu valor não será modificado em nenhum lugar do sistema. Isso evita erros e problemas de concorrência que podem ocorrer quando vários threads tentam modificar o mesmo objeto ao mesmo tempo, por exemplo. Ou seja, uma classe imutável é naturalmente thread-safe. Além disso, esses objetos também podem ser armazenados em cache com segurança, pois não mudarão.

Para desenvolver uma classe imutável , até o java 16, é necessário:

- Criar a classe como "final", para garantir  que ela não possa ser estendida, evitando que sub classes tenham acesso aos seus dados;
- Todos os campos devem ser declarados como finais e privados;
- Os atributos devem ser iniciados no construtor da classe;
- Não fornecer métodos que modifiquem o estado do objeto(setters);

```
public final class Pessoa{

    private final String nome;
    private final int idade;

    public Pessoa(String nome, int idade){
        this.nome = nome;
        this.idade = idade;
    }

    public String getNome() {
        return this.nome;
    }

    public int getIdade() {
        return this.idade;
    }
}

```

A partir do Java versão 16, é possível utilizar os records para essa finalidade. 

Um Record é um tipo de classe que armazena dados, similar a um Java Bean e que já é imutável por padrão. Ela estende implicitamente de Record, e também são implicitamente final. 
Essas classes ao serem criadas, já possuem os métodos equals, hashCode e toString() além de um método assessor para cada atributo, com o mesmo nome do atributo.

```
public record Pessoa(String nome, int idade) {}
```
Basta definir na declaração da classe os seus componentes(que neste exemplo são String nome e int idade) e você já "ganha" os metodos: nome(), idade(), equals, hashCode e toString().

Portanto, com apenas algumas linhas de código você pode criar uma classe de dados imutável. Isso pode ser muito útil quando precisamos representar objetos simples e garantir que seu estado não será alterado.


Observação: Records em Java, assim como as classes final, fornecem imutabilidade apenas para seus próprios componentes (atributos). Se uma classe record tiver referências a objetos mutáveis como componentes, esses objetos em si não se tornarão automaticamente imutáveis por estarem contidos em um record. 
Exemplo: Um record "Pessoa" que tem um atributo que referencia a um objeto "Endereço" mutável. Neste caso, a instância de Pessoa em si é imutável, ou seja, você não pode alterar seus atributos depois que o objeto Pessoa é criado. No entanto, o "Endereço" ainda é mutável, o que significa que você pode modificar o endereço após a criação do objeto Pessoa. Exemplo: 
```
Endereco endereco = new Endereco("Brasil", "Sao Paulo");
Pessoa pessoa = new Pessoa("Maria", endereco);
pessoa.getEndereco().setEstado("XXX"); 
```

Isso não é impedido pelo record, nem pelas classes final. Portanto, para garantir a imutabilidade certifique-se de que objetos imutáveis não estejam vinculados à objetos mutáveis ou ofereça cópias defensivas de quaisquer vínculos à objetos mutáveis.