This content originally appeared on DEV Community and was authored by Diego de Sousa Brandão
Introdução
A eterna busca por reduzir o código boilerplate em Java ganhou duas ferramentas poderosas: Java Records (introduzidos no Java 14 e estabilizados no Java 16) e Lombok (biblioteca amplamente adotada há anos). Embora ambos ataquem o mesmo problema – a verbosidade do Java – eles fazem isso de maneiras fundamentalmente diferentes, com implicações importantes para o design e arquitetura do seu código.
Este artigo vai além da comparação superficial de sintaxe e mergulha nas diferenças semânticas, casos de uso práticos e trade-offs de cada abordagem.
Records Java: Mais que Redução de Boilerplate
O que são Records?
Records não são apenas uma forma concisa de criar classes – eles são tipos de produto com semântica específica. Segundo a JEP 395:
“Records são portadores transparentes de dados imutáveis”
A palavra-chave aqui é transparente. Records seguem o princípio:
“A API de um record modela o estado, todo o estado, e nada além do estado”
Exemplo Básico
// Antes: 40+ linhas de código boilerplate
public 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 nome; }
    public int getIdade() { return idade; }
    @Override
    public boolean equals(Object o) { /* implementação */ }
    @Override
    public int hashCode() { /* implementação */ }
    @Override
    public String toString() { /* implementação */ }
}
// Depois: 1 linha
public record Pessoa(String nome, int idade) {}
Características dos Records
- 
Imutabilidade por Design: Todos os campos são 
private final - Transparência: Não há estado oculto
 - Construtores Canônicos: Gerados automaticamente
 - 
Métodos Padrão: 
equals(),hashCode(),toString()implementados automaticamente - Acessores: Métodos com o mesmo nome dos componentes
 
Lombok: Flexibilidade Através de Anotações
O que é Lombok?
Lombok é uma biblioteca que gera código em tempo de compilação através de anotações. Não impõe semântica específica – é pura redução de boilerplate.
Exemplo com Lombok
@Data
public class Produto {
    private String nome;
    private double preco;
    // Método personalizado
    public void aplicarDesconto(double desconto) {
        this.preco -= desconto;
    }
}
Principais Anotações
- 
@Data: Gera getters, setters,equals(),hashCode(),toString() - 
@Value: Classe imutável (equivalente a um record) - 
@Builder: Padrão Builder - 
@Slf4j: Injeção de logger - 
@Getter/@Setter: Getters e setters específicos 
Comparação Detalhada
| Aspecto | Records | Lombok | 
|---|---|---|
| Semântica | Tipos de produto transparentes | Geração de código | 
| Imutabilidade | Por padrão | Opcional (@Value) | 
| Flexibilidade | Limitada | Alta | 
| Herança | Não suportada | Suportada | 
| Estado Oculto | Proibido | Permitido | 
| Dependência Externa | Não | Sim | 
| Versão Java | 14+ (estável no 16+) | Qualquer | 
| Desempenho | Nativo | Geração em tempo de compilação | 
Quando Usar Records
  
  
  
 Use Records para:
1. DTOs (Data Transfer Objects)
public record UsuarioDTO(String nome, String email, LocalDate nascimento) {}
2. Objetos de Valor
public record Dinheiro(BigDecimal valor, String moeda) {}
3. Respostas de API
public record ApiResponse<T>(T dados, int status, String mensagem) {}
4. Configurações Imutáveis
public record DatabaseConfig(String url, String usuario, int timeout) {}
5. Entidades JPA Simples (com limitações)
@Entity
public record Produto(
    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    Long id,
    String nome,
    BigDecimal preco
) {}
  
  
  
 Evite Records quando:
- Precisar de mutabilidade
 - Necessitar de herança
 - Requerer estado oculto
 - Trabalhar com frameworks que exigem construtores sem argumentos
 - Precisar de métodos de ciclo de vida JPA complexos
 
Quando Usar Lombok
  
  
  
 Use Lombok para:
1. Entidades JPA Complexas
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Usuario {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nome;
    private String email;
    @OneToMany(mappedBy = "usuario", cascade = CascadeType.ALL)
    private List<Pedido> pedidos = new ArrayList<>();
}
2. Modelos de Negócio com Comportamento
@Data
@Slf4j
public class ContaBancaria {
    private String numero;
    private BigDecimal saldo;
    public void sacar(BigDecimal valor) {
        log.info("Sacando {} da conta {}", valor, numero);
        if (saldo.compareTo(valor) >= 0) {
            saldo = saldo.subtract(valor);
        } else {
            throw new IllegalArgumentException("Saldo insuficiente");
        }
    }
}
3. Builders Complexos
@Builder
@Data
public class Relatorio {
    private String titulo;
    private LocalDate dataInicio;
    private LocalDate dataFim;
    private List<String> colunas;
    private Map<String, Object> parametros;
}
// Uso
Relatorio relatorio = Relatorio.builder()
    .titulo("Vendas Mensais")
    .dataInicio(LocalDate.now().minusMonths(1))
    .dataFim(LocalDate.now())
    .colunas(Arrays.asList("produto", "quantidade", "valor"))
    .build();
  
  
  
 Evite Lombok quando:
- O projeto exigir zero dependências externas
 - Houver problemas de compatibilidade com IDEs
 - A equipe não estiver familiarizada com a biblioteca
 - Precisar de garantias semânticas específicas
 
Casos de Uso Práticos
Cenário 1: Sistema de E-commerce
// DTO para resposta da API - USE RECORD
public record ProdutoResponse(
    Long id,
    String nome,
    BigDecimal preco,
    String categoria
) {}
// Entidade JPA com comportamento - USE LOMBOK
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Produto {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String nome;
    private BigDecimal preco;
    private String categoria;
    private Integer estoque;
    public void reduzirEstoque(int quantidade) {
        if (estoque < quantidade) {
            throw new IllegalArgumentException("Estoque insuficiente");
        }
        this.estoque -= quantidade;
    }
}
Cenário 2: Sistema Bancário
// Objeto de valor imutável - USE RECORD
public record Moeda(String codigo, String nome, String simbolo) {}
// Entidade complexa com estado mutável - USE LOMBOK
@Entity
@Data
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@NoArgsConstructor
@Slf4j
public class Conta {
    @Id
    @EqualsAndHashCode.Include
    private String numero;
    private BigDecimal saldo;
    private String titular;
    @OneToMany(mappedBy = "conta", cascade = CascadeType.ALL)
    private List<Transacao> transacoes = new ArrayList<>();
    public void transferir(BigDecimal valor, Conta destino) {
        log.info("Transferindo {} de {} para {}", valor, this.numero, destino.numero);
        // Lógica de transferência
    }
}
Híbrido: Usando Records e Lombok Juntos
// Record com anotações do Lombok para funcionalidades adicionais
@Slf4j
public record ProcessamentoResult(
    String id,
    LocalDateTime timestamp,
    boolean sucesso,
    String mensagem
) {
    public ProcessamentoResult {
        log.info("Resultado do processamento {}: {}", id, sucesso ? "SUCESSO" : "FALHA");
    }
}
O Futuro: Spring Data Commons Recomenda Records
O Spring Framework oficialmente recomenda Records para DTOs e projeções:
// Recomendação oficial do Spring Data
public record NamesOnly(String firstname, String lastname) {}
// Em vez de usar Lombok
@Value
class NamesOnly {
    String firstname, lastname;
}
Diretrizes para Tomada de Decisão
Escolha Records quando:
 Estiver no Java 16+
 Precisar de objetos imutáveis
 Quiser garantias semânticas fortes
 Criar DTOs ou objetos de valor
 Buscar máxima performance (sem overhead de biblioteca)
Escolha Lombok quando:
 Precisar de flexibilidade máxima
 Trabalhar com herança
 Requerer mutabilidade
 Usar versões antigas do Java
 Precisar de funcionalidades como @builder ou @Slf4j
Use Ambos quando:
 Records para DTOs e objetos de valor
 Lombok para entidades e modelos de negócio
 Aproveitar o melhor de cada abordagem
Migração Gradual
Estratégia de Migração para Records:
- Identifique candidatos: DTOs, objetos de valor, classes imutáveis simples
 - Migre gradualmente: Comece com classes menos críticas
 - Teste thoroughly: Verifique serialização e frameworks
 - Monitore performance: Records podem ter características diferentes
 
Exemplo de Migração:
// Antes (Lombok)
@Value
public class Endereco {
    String rua;
    String cidade;
    String cep;
}
// Depois (Record)
public record Endereco(String rua, String cidade, String cep) {}
Considerações de Performance
Records:
 Sem overhead de biblioteca
 Otimizações do compilador
 Criação de objetos em atualizações (imutabilidade)
Lombok:
 Código gerado otimizado
 Dependência de bibliotecas externas
 Possível overhead de reflection em algumas situações
Conclusão
A escolha entre Records e Lombok não é uma questão de “melhor” ou “pior”, mas sim de adequação ao contexto:
- Records brilham quando você precisa de semântica forte, imutabilidade e transparência
 - Lombok excele quando você precisa de flexibilidade, mutabilidade e compatibilidade com versões antigas
 
A tendência é usar ambos estrategicamente:
- Records para DTOs, objetos de valor e dados imutáveis
 - Lombok para entidades complexas e modelos de negócio
 
Com o Java evoluindo e mais projetos adotando versões recentes, Records estão se tornando a escolha padrão para muitos casos de uso. No entanto, Lombok continuará relevante para cenários que demandam máxima flexibilidade.
A chave é entender que essas ferramentas resolvem problemas similares de maneiras diferentes, e a escolha certa depende das necessidades específicas do seu projeto, versão do Java e arquitetura da aplicação.
Referências Bibliográficas
- Replace Some Lombok Features with record in Java 17: A Modern Alternative
 - https://github.com/spring-projects/spring-data-commons/commit/959bde4d37b10342d963cf47d0bbf1b68000ff6a
 - https://github.com/spring-projects/spring-data-commons/pull/2794
 - https://medium.com/@fabio.alvaro/records-ou-lombok-qual-a-melhor-escolha-para-o-seu-projeto-java-b0d1fde468f2
 - https://javatechonline.com/java-records-vs-jpa-entities-and-lombok/
 
This content originally appeared on DEV Community and was authored by Diego de Sousa Brandão