Records vs Lombok @Value for DTOs — Interview Questions
Reviewed by Gurusankar M.
Short Answer
Both produce an immutable class with a canonical constructor, accessors, equals(), hashCode(), and toString() — but Records (finalized in Java 16) are a real language feature the compiler generates and understands directly, with no build-time dependency, no annotation-processor step, and first-class support in pattern matching and switch; Lombok's @Value is a compile-time annotation processor bolted onto a normal class, which predates Records and still offers things Records don't, like builder-style generation (@Builder) and the ability to extend a superclass, since a Record can't extend another class.
On this page
Concept Made Simple
Coffee Chat Question
“Records vs Lombok @Value for DTOs — what do you actually gain and lose?”
Remember It Faster
Mind Map Answer
The core distinction is language feature vs external tool: a Record's shape is enforced by javac itself, so every Java developer and every other tool (IDEs, pattern matching, reflection) understands it uniformly. Lombok generates equivalent bytecode via annotation processing, which works well but is invisible in the source until you know Lombok's conventions.
- Records
- Language feature (Java 16+); no dependency; can't extend a class
- Lombok @Value
- Annotation processor; needs the Lombok dependency + IDE plugin
- Pattern matching
- Records get first-class deconstruction patterns; Lombok classes don't
- Builders / inheritance
- Lombok (@Builder, extends) still fills gaps Records don't cover
Key takeaway: on Java 17+, Records are the default choice for a plain immutable data carrier; Lombok remains relevant specifically where its extra generators (builders, inheritance-friendly value classes) cover a gap Records structurally can't.
Learn by Doing
Hands-on Keyboard
// Record: compiler-generated, no dependency, with a validating compact constructor
public record OrderDto(String id, BigDecimal total) {
public OrderDto { // compact constructor — runs before field assignment
if (total.signum() < 0) throw new IllegalArgumentException("negative total");
}
}
// Lombok equivalent: same shape, requires the Lombok dependency + annotation processing
@Value
public class OrderDtoLombok {
String id;
BigDecimal total;
}
// Lombok can additionally generate a builder (@Builder) — Records have no built-in builderThink Beyond the Expected
What If?
Why can't a Record extend another class the way a Lombok @Value class can?
Every Record implicitly extends java.lang.Record, and Java doesn't support multiple inheritance of state — allowing a Record to also extend a user class would mean combining two sets of inherited fields in a way the language's single-inheritance model doesn't support. This is a deliberate language-level constraint, not a missing feature Lombok simply implements better.
Real World
Teams standardizing on Java 17+ for new services increasingly default to Records for DTOs and drop the Lombok dependency for that use case entirely, keeping Lombok (if at all) only for classes needing @Builder or inheritance Records structurally can't provide — this also removes a build-time annotation-processor dependency and IDE-plugin requirement that occasionally causes friction (stale generated code, IDE support lag on new Lombok versions).
Real Talk from Guru
If I'm starting a new Java 17+ codebase, I reach for Records first for DTOs, and only bring in Lombok for the specific gap it fills — usually @Builder on a more complex object. I wouldn't rip Lombok out of an existing large codebase just for consistency; that's churn without a real payoff.
Interviewer's Expectation
Keywords they're listening for:
- Knows Records are a compiler/language feature, Lombok is an annotation processor
- Names the compact constructor as Records' validation mechanism
- Knows Records can't extend a class
- Identifies a concrete gap (builders, inheritance) where Lombok still applies
Common Mistakes
- Assuming Records and Lombok @Value are strictly interchangeable
- Not knowing Records can't extend another class
- Migrating everything to Records without checking for a builder/inheritance dependency
Best Practices
- Default to Records for new immutable DTOs on Java 17+
- Keep Lombok only for the specific gaps Records don't cover
- Use a compact constructor for Record-level validation instead of a separate factory
Follow-up Questions
- How does a Record's compact constructor differ from a canonical constructor?
- How do Records interact with pattern matching in a switch expression?
- Would you migrate an existing large Lombok codebase to Records — why or why not?
Continue Learning with AI
Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly — AI is your learning companion, not a shortcut.
Plain-language foundations
I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner. Topic: OOP (Core Java) Interview question: "Records vs Lombok @Value for DTOs — what do you actually gain and lose?" Please: 1. Explain the core idea in simple, plain language, using an everyday analogy. 2. Define any technical terms you use. 3. Walk through one small, concrete example. 4. Finish with a single sentence I can easily remember. Keep the tone friendly and assume I'm new to this topic.
Was this answer helpful?
Affiliate links
Tools for Your Developer Workspace
Equipment for a comfortable, productive setup.
As an Amazon Associate I earn from qualifying purchases.
- MonitorView on Amazon : BenQ EW2790U 27-inch Monitor (opens in a new tab)
BenQ EW2790U 27-inch Monitor
- LaptopView on Amazon : Acer Aspire One Laptop (opens in a new tab)
Acer Aspire One Laptop
- Office ChairView on Amazon : Wakefit Gravita Ergonomic Office Chair (opens in a new tab)
Wakefit Gravita Ergonomic Office Chair