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.
- Implicit uforanderlighed: record-felter er
final; de genererede accessors er simple getters (ingen setters). - Autogenererede metoder:
equals,hashCodeogtoStringoprettes 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.
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]
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");
}
}
}
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();
}
}
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);
}
}
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);
};
}
- 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).
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.