What is a Java record, and what does the compiler generate for you from its components?
answer
- record Header(components) {}
- private final field + same-name accessor per component
- auto equals / hashCode / toString from all components
- accessor is x(), not getX()
- implicitly final, extends java.lang.Record
basics
~20 sA record is a compact class for holding immutable data. You list its components in the header, and the compiler auto-generates a private final field plus an accessor for each, a constructor, and equals, hashCode, and toString.
solid answer
~40 sA record is a special class declared as `record Point(int x, int y) {}`. The names in parentheses are its components. For each component the compiler creates a `private final` field and a public accessor method named exactly after the component (e.g. `x()`, not `getX()`). It also generates a canonical constructor that takes all components, plus value-based `equals`, `hashCode`, and `toString` derived from all components. The result is an immutable data carrier with almost no boilerplate. Records are implicitly `final`, extend `java.lang.Record`, and cannot extend another class. Introduced as a preview in Java 14 and finalized in Java 16, records are ideal for DTOs, map keys, and return types that bundle several values.
code
java · 11 linespublic record Point(int x, int y) { }
// Usage
Point p = new Point(1, 2);
int a = p.x(); // accessor named after the component (not getX)
int b = p.y();
System.out.println(p); // Point[x=1, y=2] -> generated toString
Point q = new Point(1, 2);
System.out.println(p.equals(q)); // true -> value-based equals
System.out.println(p.hashCode() == q.hashCode()); // truego deeper
Can declare a record, list its components, and use the generated accessor, equals, and toString. Knows accessors are x() not getX().
Explains exactly what the compiler generates (field, accessor, canonical constructor, equals/hashCode/toString) and that records are immutable and implicitly final.
Articulates the design intent (transparent immutable data carrier), the value-based equality contract derived from all components, the java.lang.Record superclass constraint, and good use cases (DTOs, keys, return types) vs. where a normal class is better.
Frames records as nominal product types / value-based aggregates, discusses how value-based equality enables safe use as keys and in pattern-matching deconstruction, and weighs API/compatibility implications of exposing records across module or library boundaries.
## What problem records solve Before records, a simple immutable data class in Java required a lot of repetitive ("boilerplate") code: a private field per value, a constructor, a getter per field, and hand-written `equals`, `hashCode`, and `toString`. This was tedious and error-prone. A **record** is a concise way to declare a class whose main purpose is to **carry data**. ## Anatomy of a declaration ```java public record Point(int x, int y) { } ``` - The keyword `record` replaces `class`. - The list in parentheses `(int x, int y)` is the **record header**, and each entry (`x`, `y`) is a **component**. A component is just a named, typed piece of data the record holds. - The body `{ }` can be empty — everything essential is generated. ## What the compiler generates From the components, the compiler automatically produces: 1. **A `private final` field per component.** `final` means it is assigned once and never changes — this is what makes records immutable by default. (Immutable = its state cannot be modified after construction.) 2. **A public accessor method per component**, named *exactly* after the component — `x()` and `y()`, **not** `getX()`/`getY()`. Java records deliberately drop the JavaBeans `get` prefix. 3. **A canonical constructor** taking all components in declared order, which assigns each argument to the matching field. 4. **`equals(Object)`** — two records are equal when they are the same record type and *all* their components are equal (value-based equality, not reference identity). 5. **`hashCode()`** — derived from all the components, consistent with `equals`. 6. **`toString()`** — a readable form like `Point[x=1, y=2]`. ## Built-in constraints - A record is **implicitly `final`** — you cannot subclass it. - It **implicitly extends `java.lang.Record`** — so it cannot extend any other class (Java has single inheritance of implementation), but it *can* implement interfaces. - You may not add extra **instance** fields beyond the components (static fields are allowed). ## When to use one Records shine for **DTOs** (data transfer objects), **value objects**, multi-value return types, and **map/set keys** (because correct `equals`/`hashCode` come for free). Avoid them when you need mutable state or an inheritance hierarchy. ## History Records were a preview feature in Java 14 (2020) and became a permanent language feature in Java 16 (2021).
- Why are record accessors named x() instead of getX()?Records intentionally break with the JavaBeans get/set convention. The accessor name matches the component name exactly, signaling that a record is a transparent data carrier rather than a mutable bean. The language designers chose `x()` to read as 'the x of this record' and to allow component names to drive the API directly.
- Can a record have zero components?Yes. `record Empty() {}` is legal — it produces a class with no fields, a no-arg canonical constructor, and equals/hashCode/toString based on no components (so all instances are equal). It is occasionally used as a sealed-hierarchy marker.
Think of a record as a pre-printed shipping label: you fill in the fixed boxes (the components) once, the label is sealed (immutable), and anyone can read the boxes back — but nobody re-prints over them.
saying these in an interview costs you the question
- Calling the accessor getX() — records use x() with no get prefix.
- Saying records are mutable — components are private final, so a record's own fields cannot be reassigned.
- Claiming the compiler generates setters — records have no setters by design.
- Saying a record can extend another class — it implicitly extends java.lang.Record and Java forbids multiple class inheritance.
- Confusing a record with a regular class that simply has fewer lines — the generated equals/hashCode/toString and the final-field guarantees are part of the language contract.