Unit 09 · lesson

Records Make Value-Shaped Data Explicit

Some domain concepts are primarily immutable bundles of named values.

Java records make that intent concise.

record SensorReading(String sensorId, double value, long timestamp) {}

Create values:

var reading = new SensorReading("front", 12.5, 1000L);

IO.println(reading.sensorId());
IO.println(reading.value());

The components are named and accessible through generated accessor methods.

Why a record is more than fewer lines

A record communicates a design decision:

This type is primarily a transparent carrier for this fixed set of values.

Java supplies component accessors and value-oriented equals, hashCode, and toString behavior based on the record components.

That makes records a strong fit for things like:

  • coordinates;
  • immutable measurements;
  • result values;
  • parsed input rows;
  • small configuration facts.

Class when behavior/identity/lifecycle need more control

A mutable bank account, connection, game session, or robot subsystem often has lifecycle and behavior that should not be reduced to "a tuple of fields."

Use a class when you need more deliberate control over state transitions, encapsulation, inheritance, or identity.

Do not make the rule "records for small things, classes for big things." Size is not the key distinction.

Compare equality

record Point(int x, int y) {}

var a = new Point(2, 3);
var b = new Point(2, 3);

IO.println(a.equals(b));

The two record instances have the same component values, so value equality reports true.

Now compare object identity with ==. Do not confuse these questions:

same reference/object identity?
same logical value according to equals?

Records can still validate construction

A record can define a compact constructor:

record Percentage(double value) {
    Percentage {
        if (value < 0 || value > 100) {
            throw new IllegalArgumentException("percentage out of range");
        }
    }
}

Now invalid values cannot be constructed through the normal record constructor.

Design comparison

Model SensorReading twice:

  1. as a normal class with public fields;
  2. as a record.

Compare:

  • construction;
  • access;
  • mutation expectations;
  • equality intent;
  • debugging output;
  • validation options.

Then choose the model that better represents an immutable measurement event.

Evidence

Submit one class-versus-record decision. Your justification must describe the domain semantics: identity, mutability, invariant, lifecycle, or value equality.

"Record uses fewer lines" is an observation, not the design argument.