A Java record makes a small data carrier read like the domain it represents instead of like its supporting boilerplate. Declare components in the header; the compiler supplies underlying fields, accessors, `toString`, `equals`, and `hashCode`. The body can still hold additional methods when the data needs them. section 4.2.1 section 4.4
Normalize data at construction
A compact constructor keeps construction rules beside the data without repeating field assignments. This `Person` record turns null names into empty strings and normalizes both names to lowercase before storage. section 4.2.1
public record Person(String firstname, String lastname) {
public Person {
firstname = Objects.toString(firstname, "").toLowerCase();
lastname = Objects.toString(lastname, "").toLowerCase();
}
}
The compact constructor has an implicit signature, so its code can focus on transforming or validating components rather than assigning fields. section 4.2.1
Use records when values are lightweight, immutable, and meaningful as a group. Prefer domain-shaped components such as `Age`, `HeightInInches`, and `WeightInPounds` over loosely interpreted primitives or generic containers. The resulting call sites and return types reveal what each value means, while behavior can remain in dedicated methods and classes. section 4.2.2 section 4.4
Make a physical profile explicit
A `PhysicalProfile` can combine `Gender`, `Age`, `WeightInPounds`, and `HeightInInches`; each value record can validate its own range. A BMI computation can then return records such as `BmiStat` and `BmiGlobalResult` instead of a `List<Object>` or a collection of unclear nested values. section 4.2.2 section 4.2.2
Records also work with pattern matching to route data to the right logic. In enhanced switches, a `PhysicalProfile` can be matched as a whole or deconstructed into components, letting adult and child BMI handling express the values it needs. Java 21 enables records in this pattern-matching style. section 4.2.2
Keep the tradeoff visible:
- Use a compact constructor for normalization, sanitization, or validation at initialization time. section 4.2.1
- Avoid oversized record headers: many components make canonical construction and call sites harder to read; regroup related values into smaller records or use a builder. section 4.2.1
- Do not over-model: explicit small carriers clarify meaning, but unnecessary structure adds complexity. section 4.4
A useful rule is to model data first. When a value has a stable meaning, give it a small explicit carrier; let records remove the repetitive mechanics, and keep transformations and calculations named outside the carrier where that better separates behavior from data. section 4.4 section 4.2.2



