Phase 20 of 20 · Topic 20.1

Record Classes (Java 16+) & Immutable Data Transfer Objects

1Concept

Records provide concise, boilerplate-free immutable data carrier classes. The compiler automatically generates `final` fields, canonical constructor, accessors, `equals()`, `hashCode()`, and `toString()`. Records support Compact Constructors for input validation.

2Architecture Diagram

record UserDto(String id, String email) {}
       |
       v javac generates automatically:
- final fields (id, email)
- canonical constructor
- accessors id(), email()
- equals(), hashCode(), toString()

3Code Example

Core Java
public class RecordMasteryDemo {
    public record Transaction(String txId, double amount, String currency) {
        // Compact Constructor: clean validation without field assignment boilerplate
        public Transaction {
            if (amount <= 0) {
                throw new IllegalArgumentException("Amount must be positive");
            }
            if (currency == null || currency.isBlank()) {
                currency = "USD";
            }
        }
    }

    public static void main(String[] args) {
        Transaction tx = new Transaction("TX-98214", 349.50, "USD");
        System.out.println("Record instance: " + tx);
        System.out.println("Accessor txId(): " + tx.txId());
        System.out.println("Accessor amount(): $" + tx.amount());
    }
}

4Expected Output

Record instance: Transaction[txId=TX-98214, amount=349.5, currency=USD]
Accessor txId(): TX-98214
Accessor amount(): $349.5

5Key Takeaways

  • Records cannot extend other classes (they implicitly extend `java.lang.Record`), but can implement interfaces.
  • Record components are shallowly immutable; if a record holds a mutable List, list elements can still change.
  • Use compact constructors for input validation and normalization.