Record — Interview Q&A¶
50 questions on records, patterns, design, and runtime behavior.
Section A — Basics (1-10)¶
Q1. What is a Java record? A: A concise, immutable data carrier introduced in Java 14 (preview) and standardized in Java 16. Declared with the record keyword and a header listing components.
Q2. What does the compiler auto-generate for a record? A: A canonical constructor, accessor methods (one per component), and equals/hashCode/toString. All can be overridden if needed.
Q3. What's the accessor naming convention? A: Components are accessed via methods named after them: point.x(), not point.getX().
Q4. Are records mutable or immutable? A: Immutable. Component fields are private final. No setters.
Q5. Can a record extend another class? A: No. Records implicitly extend java.lang.Record and are implicitly final.
Q6. Can a record implement interfaces? A: Yes. Records can implement multiple interfaces.
Q7. Can a record have additional instance fields? A: No. Only components become instance fields. Static fields are allowed.
Q8. Can a record have static methods? A: Yes — static fields, methods, factory methods, etc., all allowed.
Q9. What's a compact constructor? A: A constructor declared without parameter list, used for validation/normalization. The implicit field assignments happen after the body.
Q10. Can records be generic? A: Yes. record Pair<A, B>(A first, B second) { }.
Section B — Design (11-20)¶
Q11. When should I use a record? A: When you need an immutable bundle of related values: DTOs, value objects, tuples, message classes, sealed-type variants.
Q12. When should I NOT use a record? A: When the class needs mutable state, must extend another class, has substantial business logic, or is a service/controller.
Q13. What's the difference between record and POJO with getters? A: Records are immutable (no setters), final, auto-generate equals/hashCode/toString, use field-name accessors. Less boilerplate.
Q14. Can you replace all data classes with records? A: Most, but not all. JPA entities typically need no-arg constructors and setters; not all ORMs support records yet. DTOs work great as records.
Q15. How do you handle "modify and return new" for records? A: Manual withX(value) methods that construct a new record with one field changed. JEP 468 may add built-in syntax.
Q16. How do records relate to sealed interfaces? A: Sealed interface + records = algebraic data types. Each variant is a record carrying typed data; the sealed interface closes the hierarchy.
Q17. What's a record pattern? A: Java 21+ feature for deconstruction: if (obj instanceof Point(int x, int y)). Binds the components to variables.
Q18. Can records be used as map keys? A: Yes. Records have proper equals/hashCode based on components. Same-content records are equal.
Q19. Should records have behavior or just data? A: Mostly data. Methods that operate on the components are fine (Point.distance(Point), Money.add(Money)). Heavy business logic belongs elsewhere.
Q20. Can records have nested types? A: Yes — nested records, classes, interfaces, enums. All work normally.
Section C — Constructors & validation (21-30)¶
Q21. What's the canonical constructor? A: The constructor whose parameters match the record components in order. Auto-generated unless explicitly declared.
Q22. Can I have multiple constructors in a record? A: Yes — additional constructors must delegate to the canonical via this(...) as the first statement.
Q23. Where do you put validation in a record? A: In the compact constructor. It runs before the implicit field assignment.
Q24. Can I reassign fields in the compact constructor? A: You can mutate the parameter variable (x = Math.abs(x)), and the modified value gets assigned. You cannot use this.x = ... directly in compact form (that's the explicit canonical).
Q25. What's the difference between compact and explicit canonical constructor? A: Compact has no parameter list and no explicit field assignments (assignment is implicit). Explicit canonical has both. Functionally equivalent.
Q26. Can a record canonical constructor call super(...)? A: It implicitly calls Record.<init>(). You cannot explicitly call super(...) in records.
Q27. Can a record canonical constructor throw checked exceptions? A: Yes, like any constructor.
Q28. What if I forget defensive copying for a mutable list component? A: The record holds the caller's reference. Mutations to the original list affect the record. Add values = List.copyOf(values) in the compact constructor.
Q29. Is a compact constructor's body run during deserialization? A: Yes. Java deserialization uses the canonical constructor, which runs the compact body. Validation re-runs.
Q30. Can compact constructor have a return statement? A: No. The implicit field assignment must occur; an early return would skip it.
Section D — Pattern matching (31-40)¶
Q31. What are record patterns? A: Patterns that deconstruct records into their components. obj instanceof Point(int x, int y) binds x and y.
Q32. Can you nest record patterns? A: Yes. Pair(Point(int x, int y), int v) binds x, y, v if the structure matches.
Q33. How does pattern matching enforce exhaustiveness? A: For sealed types, the compiler checks every permitted variant has a case. For records implementing sealed interfaces, this works seamlessly.
Q34. Can var be used in patterns? A: Yes. case Point(var x, var y) infers each component's type.
Q35. What's a guarded pattern? A: A pattern with a when clause: case Point(var x, var y) when x > 0. The pattern matches only if both type-shape and condition hold.
Q36. Can patterns appear in switch? A: Yes (Java 21+). switch (obj) { case Point(int x, int y) -> ...; }.
Q37. Can patterns appear in instanceof? A: Yes. if (obj instanceof Point(int x, int y)) — also Java 21+.
Q38. What if the receiver is null in a pattern switch? A: Without an explicit case null, it throws NullPointerException. With case null, it's matched.
Q39. Are patterns checked at compile or runtime? A: Both. The compiler checks structural fit and exhaustiveness; the JVM checks values at runtime.
Q40. What's the bytecode for record patterns? A: invokedynamic to SwitchBootstraps.typeSwitch for type matching, plus accessor calls (record.x(), record.y()) to extract components.
Section E — Edge cases & advanced (41-55)¶
Q41. Can records have annotations on components? A: Yes. They apply to the record component itself and the corresponding field/parameter/accessor (depending on the annotation's @Target).
Q42. What's Class.isRecord()? A: Returns true if the class has a Record attribute (i.e., declared as a record).
Q43. What's Class.getRecordComponents()? A: Returns an array of RecordComponent describing each component: name, type, accessor, annotations.
Q44. Can I serialize a record with Java serialization? A: Yes. The default behavior writes components and reconstructs via canonical constructor. Validation re-runs.
Q45. Can Jackson serialize records? A: Yes since Jackson 2.12. Default uses component names; @JsonProperty works on components.
Q46. Can Hibernate use records as entities? A: Limited. Records work as @Embeddable since Hibernate 6. Full entity support is awkward (records have no setters; some Hibernate features assume them).
Q47. Can a record be Cloneable? A: Technically yes, but pointless — records are immutable, so cloning makes no sense. Just share the reference.
Q48. What's the cost of a record allocation vs an int field? A: A record has object header overhead (~16 bytes). For pure number-crunching, primitives are cheaper. But escape analysis often eliminates short-lived records.
Q49. Can records be hidden classes? A: Yes. Lookup.defineHiddenClass works for records. Used in some advanced framework code.
Q50. Why is Record abstract? A: To force every concrete record class to provide proper equals/hashCode/toString. The abstract methods can be auto-generated by the compiler or written explicitly.
Bonus — staff (51-55)¶
Q51. How would you migrate a 30-field POJO to a record? A: Step 1: identify which fields are truly canonical state. Step 2: split into smaller records if the data is too wide. Step 3: convert. Step 4: update callers (getters → accessors). Step 5: replace setters with withX or builder patterns.
Q52. Is there a way to copy a record with one field changed without writing withX methods? A: Until JEP 468 (or successor) standardizes with syntax, no. You must write withX methods or use a builder.
Q53. What's the future of records? A: Built-in with syntax, deeper pattern matching (nested + guards combined), value classes (Project Valhalla) make records flat in memory.
Q54. How does Project Valhalla affect records? A: Value classes will be similar to records but without identity. Records can be considered "objects with identity"; value classes are "data without identity, flat in memory."
Q55. When wouldn't you use a sealed interface + records pattern? A: When variants are open-ended (plugins). When variants don't carry data (use enums). When the variants are all just labels (enum is more compact).
Use this list: mix one Q from each section. Strong candidates demonstrate they understand records as a design tool, not just a syntactic shortcut.