Part 2 · Fundamentals

Types, objects, records and domain invariants

Prerequisites: 01-ecosystem

Why can a final reference still change?

Reference A: points to a list; Reference B: points to same list; Mutable list: shared object. Connections: Reference A to Mutable list (alias); Reference B to Mutable list (alias)
Reference identity and object state are different; defensive copies break unwanted sharing. [S03] [S04] [S05]

Goal & mental model verified

Separate primitive values from object references. An interface states a contract; a class implements behavior. Records express data aggregates with final component fields; they do not make referenced collections deeply immutable.

[S03] [S04]

Worked example · illustrative, not executed synthesis

record QuoteId(String value) {}
record Quote(QuoteId id, java.util.List<String> covers) {
  Quote { covers = java.util.List.copyOf(covers); }
}
// The defensive copy prevents external list mutation.
[S03] [S04] [S05]

Engineering decision synthesis

Use composition for replaceable pricing behavior and small value types for identifiers. This clarifies invariants at the cost of more explicit conversions.

[S03] [S04] [S05]

Pitfall & diagnosis synthesis

A final reference can point to a mutable object. Value equality also needs a compatible hashCode; identity equality with == answers a different question.

[S03] [S04] [S05]

Improve & validate synthesis

Move invalid-state checks into construction boundaries. Test equality, null handling and defensive copies where the business invariant depends on them.

[S03] [S04] [S05]
Keep this: A type should make the wrong state harder to represent.
Check yourself: Is a record containing ArrayList deeply immutable?

No. Its field reference is final, but the referenced list can remain mutable.

Sources & further reading

  1. [S03] JLS: types, values, variables

    Oracle / OpenJDK · specification · accessed 2026-10-09 · Java SE 25

    Supports: Primitive/reference distinction; Generics and final references

    Read the linked section to validate the mechanism and its version-specific constraints.

  2. [S04] JLS: classes and records

    Oracle / OpenJDK · specification · accessed 2026-10-09 · Java SE 25

    Supports: Inheritance and interfaces; Record components and final fields

    Read the linked section to validate the mechanism and its version-specific constraints.

  3. [S05] Object equality and hashing

    Oracle / OpenJDK · documentation · accessed 2026-10-09 · Java SE 25

    Supports: equals/hashCode contract

    Read the linked section to validate the mechanism and its version-specific constraints.