Medium java java-21

How is a record different from a traditional class?

The 30 second answer

A record's fields are always final and set through its constructor, and equals and hashCode always use all the components. A record can't extend another class, because it already extends Record, and it can't add extra instance fields. It can implement interfaces and have methods. Also, it is only shallowly immutable: a list inside can still change unless I copy it in the constructor.

RecordNormal class
Fieldsprivate final, one per componentanything
Extra instance fieldsnot allowedallowed
Superclassimplicitly java.lang.Record, can't extendany non-final class
Subclassingimplicitly finalallowed
equals / hashCode / toStringgenerated from all componentsinherited from Object unless written
Accessorsname()whatever you write

Shallow immutability is the common follow-up:

record Cart(List<Item> items) {
    Cart { items = List.copyOf(items); }   // defensive, unmodifiable copy
}

[Opinion] Use a normal class when you need mutable state, inheritance, hidden internal state or lazy fields. JPA entities should stay normal classes, because JPA needs a no-arg constructor and mutable, proxyable entities; records work well for DTOs and query projections.

Sources: JEP 395: Records, JLS 8.10 Record Classes

Sources (0)
See inline citations in the answer above.