Java Academy · Aula

Registros versus Classes versus Lombok

Compare registros com classes tradicionais e anotações Lombok para escolher a ferramenta adequada.

Aula 4 de 413 etapas

Registros versus Classes versus Lombok é uma aula grátis de Java Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Java Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Java Academy inclui 4 aulas no total.

Registros versus classes versus Lombok

Java oferece várias abordagens para criar tipos que transportam dados: classes simples com código repetitivo, registros (Java 16 ou posterior) ou anotações Lombok. A escolha certa depende do caso de uso.

O problema do código repetitivo

Uma classe Java simples para transportar dados exige muito código repetitivo: construtor, métodos de acesso, equals, hashCode e toString — tudo isso para apenas alguns campos.

// Traditional class — lots of boilerplate
class ProductOld {
    private final String id;
    private final String name;
    private final double price;

    public ProductOld(String id, String name, double price) {
        this.id = id; this.name = name; this.price = price;
    }
    public String getId() { return id; }
    public String getName() { return name; }
    public double getPrice() { return price; }

    @Override public boolean equals(Object o) { /* ... */ }
    @Override public int hashCode() { /* ... */ }
    @Override public String toString() { /* ... */ }
}

A solução com registros

Um registro reduz a mesma classe a uma linha. O compilador gera automaticamente todo o código repetitivo.

// Record — one line, same functionality
record Product(String id, String name, double price) {}

// Usage is almost identical except accessors use component names (no get prefix)
Product p = new Product("P001", "Laptop", 999.99);
System.out.println(p.id());     // P001 (not getId())
System.out.println(p.name());   // Laptop
System.out.println(p.price());  // 999.99
System.out.println(p);          // Product[id=P001, name=Laptop, price=999.99]

Lombok @Data e @Value

Lombok gera código repetitivo em tempo de compilação por meio de anotações. @Value cria uma classe imutável semelhante aos registros; @Data cria uma classe mutável.

// Lombok @Value — immutable (closest to record)
import lombok.Value;

@Value
public class LombokProduct {
    String id;
    String name;
    double price;
    // Lombok generates: all-args constructor, getters, equals, hashCode, toString
    // Note: accessors follow getX() naming convention (getPrice(), not price())
}

// Lombok @Data — mutable
import lombok.Data;
@Data
public class MutableProduct {
    private String id;
    private String name;
    private double price;
    // Generates: getters, setters, equals, hashCode, toString, no-args constructor
}

Principais diferenças

Diferenças importantes entre registros, Lombok @Value e classes comuns:

  • Nomenclatura dos acessores: os registros usam name(); o Lombok usa getName()
  • Variante mutável: os registros são sempre imutáveis; o Lombok oferece @Data para mutabilidade
  • Herança: os registros não podem estender classes; as classes Lombok podem
  • Dependência da ferramenta de compilação: o Lombok exige a configuração de um processador de anotações; os registros são integrados à linguagem

Quando usar registros

Os registros são ideais quando:

  • O tipo é principalmente um portador transparente de dados (DTO, objeto de valor)
  • A imutabilidade é desejada por princípio de design
  • Você usa Java 16 ou posterior e quer dependência zero
  • O tipo participa de correspondência de padrões (classes seladas + registros)
// Perfect record use cases:
record Coordinates(double lat, double lon) {}
record JwtClaims(String subject, String role, long expiresAt) {}
record PageRequest(int page, int size, String sortBy) {}
record ErrorResponse(int code, String message, String path) {}

// These are all simple data carriers with no mutable state

Quando usar Lombok

O Lombok é preferível quando:

  • Você precisa de beans mutáveis (por exemplo, entidades JPA e classes de configuração do Spring)
  • A nomenclatura dos acessores deve seguir a convenção JavaBeans (getX) para garantir compatibilidade com estruturas
  • Você precisa de @Builder para a construção de objetos complexos
  • É necessária mutabilidade parcial (@NonFinal em alguns campos)
// Lombok @Builder — great for complex object construction
import lombok.*;

@Builder
@Value
public class EmailMessage {
    String to;
    String from;
    String subject;
    String body;
    List<String> attachments;
}

EmailMessage msg = EmailMessage.builder()
    .to("user@example.com")
    .from("noreply@app.com")
    .subject("Welcome!")
    .body("Thank you for signing up")
    .attachments(List.of())
    .build();

Quando usar classes comuns

As classes comuns continuam apropriadas quando:

  • A classe tem comportamento complexo além do simples armazenamento de dados
  • Você precisa estender outra classe
  • É necessário um controle minucioso sobre hashCode/equals
  • É necessário estado mutável com encapsulamento
// Plain class — when behavior dominates over data
class ShoppingCart {
    private final List<CartItem> items = new ArrayList<>();
    private final String customerId;

    public ShoppingCart(String customerId) {
        this.customerId = customerId;
    }

    public void addItem(CartItem item) { items.add(item); }
    public void removeItem(String sku) { items.removeIf(i -> i.sku().equals(sku)); }
    public double total() { return items.stream().mapToDouble(CartItem::lineTotal).sum(); }
    public boolean isEmpty() { return items.isEmpty(); }
}

Combinando registros e classes

Registros e classes funcionam perfeitamente em conjunto. Use registros para dados imutáveis dentro de classes que gerenciam estado mutável.

// Record for the immutable event data
record UserEvent(String userId, String action, java.time.Instant timestamp) {
    public static UserEvent now(String userId, String action) {
        return new UserEvent(userId, action, java.time.Instant.now());
    }
}

// Class for the mutable event store
class EventLog {
    private final List<UserEvent> events = new ArrayList<>();

    public void record(String userId, String action) {
        events.add(UserEvent.now(userId, action));
    }

    public List<UserEvent> eventsFor(String userId) {
        return events.stream()
            .filter(e -> e.userId().equals(userId)).toList();
    }
}

Registros no Spring Boot

Os registros se integram bem ao Spring Boot como corpos de requisição e resposta. O mapeador Jackson do Spring os trata com configuração mínima.

// Spring Boot REST controller using records
import org.springframework.web.bind.annotation.*;

record CreateProductRequest(String name, double price, String category) {}
record ProductResponse(long id, String name, double price, String category) {}

@RestController
@RequestMapping("/api/products")
class ProductController {
    @PostMapping
    public ProductResponse create(@RequestBody CreateProductRequest req) {
        // Jackson automatically deserializes JSON into the record
        long id = productService.save(req);
        return new ProductResponse(id, req.name(), req.price(), req.category());
    }
}

Comparação de desempenho

As três abordagens produzem essencialmente o mesmo bytecode para portadores simples de dados. O desempenho é idêntico — a escolha depende da experiência do desenvolvedor e dos requisitos.

// All three compile to approximately equivalent bytecode:
// - Records: compiler-generated, always immutable
// - Lombok @Value: annotation-processor-generated, always immutable
// - Plain class: hand-written

// The key runtime difference:
// Records: accessor is a method matching field name (price() not getPrice())
// Lombok/Class: accessor follows JavaBeans (getPrice())

// Jackson compatibility:
// Records: work natively in Jackson 2.12+ with no config
// Lombok: work with @JsonProperty or jackson-databind-lombok module

Verificação rápida

Qual convenção de nomenclatura os acessores de registros seguem?

Recapitulação: registros, classes e Lombok

Principais conclusões:

  • Os registros geram automaticamente construtor, acessores (sem o prefixo get), equals, hashCode e toString
  • Os registros são sempre imutáveis; use classes comuns para estado mutável
  • O Lombok @Value se aproxima dos registros, mas usa a nomenclatura getX() e exige configuração
  • O Lombok @Builder é excelente para a construção de objetos complexos com muitos campos opcionais
  • Os registros são ideais para DTOs, objetos de valor e corpos de requisição e resposta de APIs
  • As classes comuns continuam sendo melhores quando o comportamento predomina ou quando é necessária herança
Grátis para começar

Aprenda Java com um tutor de IA — grátis

Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.

Cursos
104
Aulas
374

Perguntas Frequentes

A aula “Registros versus Classes versus Lombok” é grátis?

Sim — o texto completo de “Registros versus Classes versus Lombok” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Java Academy, atualize para CoddyKit PRO. O curso de Java Academy inclui 4 aulas no total.

O que vou aprender em “Registros versus Classes versus Lombok”?

Compare registros com classes tradicionais e anotações Lombok para escolher a ferramenta adequada. Você pratica Java Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.

Preciso ter experiência prévia para começar Java Academy?

Nenhuma experiência prévia é necessária. Java Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.

Quanto tempo leva a aula “Registros versus Classes versus Lombok”?

A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.

Posso escrever e executar código nesta aula de Java Academy?

Sim. Cada aula de Java Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.

Todas as aulas deste curso

  1. Introdução aos Registros
  2. Construtores Compactos e Validação
  3. Métodos Personalizados em Registros
  4. Registros versus Classes versus Lombok
← Voltar para Java Academy