Usando Records em Java

Willyan Guimarães
experienceCode
Published in
2 min readOct 17, 2021
Photo by Namroud Gorguis on Unsplash

Um Record, nada mais é que um tipo de classe que armazena dados. É a mesma ideia de construção similar a um JavaBean, possui construtor, atributos e métodos acessores. Porém, ao invés de possibilitar qualquer alteração a classe é imutável. Também possui os métodos equals, hashCode e toString().

Algumas boas vantagens a se considerar na utilização de records:

  • Diminuir escrita de código boilerplate
  • Tirar a necessidade de bibliotecas que fazem esse trabalho, como por exemplo, Lombok
  • Imutabilidade

Um exemplo do que estamos falando

Imagine que tenha uma classe User com nome e senha como atributos. Seria necessário essa implementação:

import java.util.Objects;

public class User {

private String name;

private String password;

public User(String name, String password) {
this.name = name;
this.password = password;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
User user = (User) o;
return name.equals(user.name) && password.equals(user.password);
}

@Override
public int hashCode() {
return Objects.hash(name, password);
}

@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", password='" + password + '\'' +
'}';
}
}

Usando records, basta declarar:

public record User(String name, String password){}

Dado a contexto de imutabilidade, existe apenas um construtor com todos os atributos. Também não existem métodos setter.

User user = new User("admin", "45454*aa");

Outra diferença entre o primeiro design e este usando records é que os métodos acessores não usam a terminologia com “get” apenas o próprio nome do atributo, ou seja, ao invés de getName(), apenas name();

String name = user.name();

Usando records para serializar/desserializar classes

Dentre várias possibilidades usando records, uma utilidade seria serializar e desserializar classes que representam payloads de comunicação, também chamados de DTOs.

Testando o Jackson na versão 2.13.0 já é possível utilizar o recurso sem nenhuma configuração específica.

@Test
void shouldDeserializeCorrectly() throws Exception {
String json =
"""
{
"name": "willyancaetano",
"password": "jK%onD2B2Pvt"
}
""";

User user = objectMapper.readValue(json, User.class);
assertEquals("willyancaetano", user.name());
assertEquals("jK%onD2B2Pvt", user.password());

}

@Test
void shouldSerializeCorrectly() throws Exception {

User user = new User("admin", "$JJMwSYskkN^");

String json = objectMapper.writeValueAsString(user);

assertTrue(json.contains("admin"));
assertTrue(json.contains("$JJMwSYskkN^"));
}

E o que mais podemos fazer utilizando Records ?

Existem possibilidades de utilizar records em outros cenários, como por exemplo:

  • Referências de registros de base de dados ou qualquer outro data-provider: Pense, registros que são buscados em um banco de dados podem ser records
  • Mensagens enviadas e recebidas de comunicação assíncrona

E aí, o que achou dessa nova feature da linguagem ? Enxerga mais alguma outro cenário que seja possível utilizar records ?

Referências:

--

--