Skip to main content
Dat 2. semester Bornholm
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

Records

Records i Java er en kompakt måde at deklarere uforanderlige / immutable data. De blev præsenteret som preview i Java 14 og standardiseret i Java 16. En “record” inkluderer automatisk equals, hashCode, toString, en kanonisk konstruktør og adgangsmetoder til hvert objekt. Brug dem når en types hovedopgave er at holde data.

Introduktion

  • Implicit uforanderlighed: record-felter er final; de genererede accessors er simple getters (ingen setters).
  • Autogenererede metoder: equals, hashCode og toString oprettes for dig på basis af record-komponenterne.
  • Kompakt syntaks: deklarér hensigten på én linje i stedet for en ordrig POJO / klasse.
  • Gode til DTO’er: passer godt til API-payloads, konfigurationsobjekter og value objects.

Grundlæggende record-deklaration

public record Point(int x, int y) {}

Brug:

Point p = new Point(3, 4);
System.out.println(p.x()); // 3
System.out.println(p);     // Point[x=3, y=4]

Kompakt konstruktør til validering

Du kan tilføje en kompakt konstruktør til validering og stadig beholde den korte syntaks.

public record Temperature(double celsius) {
    public Temperature {
        if (celsius < -273.15) {
            throw new IllegalArgumentException("Below absolute zero");
        }
    }
}

Kanonisk konstruktør til transformation

Hvis du skal normalisere input, kan du definere den fulde kanoniske konstruktør.

public record Email(String value) {
    public Email(String value) {
        this.value = value.trim().toLowerCase();
    }
}

Tilføj adfærd og statiske medlemmer

Records kan indeholde metoder og statiske medlemmer ligesom klasser.

public record Money(BigDecimal amount, Currency currency) {
    public Money add(Money other) {
        requireSameCurrency(other);
        return new Money(amount.add(other.amount), currency);
    }

    private void requireSameCurrency(Money other) {
        if (!currency.equals(other.currency)) {
            throw new IllegalArgumentException("Currency mismatch");
        }
    }

    public static Money zero(Currency currency) {
        return new Money(BigDecimal.ZERO, currency);
    }
}

Dekonstruktion med pattern matching (Java 21+)

Records fungerer godt sammen med pattern matching i switch/instanceof.

static String describe(Point p) {
    return switch (p) {
        case Point(int x, int y) when x == y -> "on diagonal";
        case Point(int x, int y)              -> "point (%d,%d)".formatted(x, y);
    };
}

Når du ikke bør bruge et record

  • Du har brug for mutabilitet eller setters.
  • Du skal udvide (nedarvning) en klasse (records udvider implicit java.lang.Record).
  • Du skal skjule komponenter (alle komponenter bliver offentlige accessor-metoder).

Migrering af en POJO til et record (mini-eksempel)

Før (POJO):

public class Customer {
    private final String id;
    private final String name;

    public Customer(String id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getId() { return id; }
    public String getName() { return name; }

    @Override public boolean equals(Object o) { /* boilerplate */ }
    @Override public int hashCode() { /* boilerplate */ }
    @Override public String toString() { /* boilerplate */ }
}

Efter (record):

public record Customer(String id, String name) {}

Resultat: mindre kode, samme semantik, uforanderlighed som standard.