public record Person (String name, String address) {}
//...
Person p = new Person("Pavel Holec", "Lipová 3, Brno");
record
)Tomáš Pitner, Radek Ošlejšek, Marek Šabo, Jakub Čecháček pitner@muni.cz
Od nových verzí Javy (14+) lze využít zjednodušenou syntaxi pro vytváření neměnných objektů, tzv. record
(záznam)
Namísto třídy class
můžeme použít record
Tím se definuje třída, kde každý objekt bude mít vlastnosti name
a address
,
které se nastaví jednou a už nejdou změnit, čili jako výše Vertex1D
.
public record Person (String name, String address) {}
//...
Person p = new Person("Pavel Holec", "Lipová 3, Brno");
record
?record
je vlastně typ tříd neměnných objektů.
Překladač pro nás automaticky pro tuto třídy vytvoří:
konstruktor mající parametr pro nastavení každého atributu (hodnoty) v objektu
přístupové metody pro čtení atributů, např. person.name()
record
Dále pak se "samy vytvoří":
metoda equals
pro porovnání objektů: dva záznamy budou stejné <⇒ jsou stejné všechny odpovídající si atributy
metoda hashCode()
konzistentní s equals()
"inteligentní" metoda toString
vracející např. Person[name=John Doe, address=100 Linda Ln.]
Jména metod jsou odlišná od konvence používané u JavaBeans nebo obecně u javových objektů:
tradičně by bylo person.getName() , ale u záznamu person.name() |
viz https://medium.com/@reetesh043/record-java-new-feature-daf97797bf3a
Záznamy snižují množství překombinovaného kódu automatickým generováním standardních implementací pro běžné úlohy, jako jsou přístupy ke čtení atributů, metody equals()
, hashCode()
a toString()
. Vývojáři se tak mohou soustředit na definici datových polí, případně i jejich chování.
Záznamy jsou ve výchozím nastavení navrženy jako neměnné, což znamená, že jakmile je objekt vytvořen, jeho stav nelze změnit. Tato vlastnost je žádoucí v mnoha scénářích, kde je důležitá integrita a konzistence dat. Zejména vede k robustnějšímu kódu u vícevláknových aplikací.
Při použití záznamů je záměr kódu přehlednější. Záznamy explicitně sdělují, že třída je především datový kontejner s určitou sadou polí.
Záznamy jsou přesto v mnoha ohledech jako běžné třídy - mohou mít konstruktory a další metody.
Cestou je vytvořit vždy nový typ, pokud nemá metody, tak to stejně nevadí.
Důvod je mj. v tom, že bychom neměli záruku, že Account je opravdu jedině Account a ne třeba CheckingAccount.
record Account(int id, String name) {}
// won't compile, cannot inherit
record CheckingAccount extends Account {}
Je to logické: ty proměnné by stejně musely být neměnné
record Account(int id, String name) {
// won't compile, cannot have other attrs
private int age;
}
public record Account(int id, String name) {
public Account(int id) {
// call of the implicit record constructor
this(id, null);
}
}
public record Person(String name, String address) {
// new syntax: no parentheses after classname
public Person {
Objects.requireNonNull(name);
Objects.requireNonNull(address);
}
}
Obvykle se proto musí doplnit metody.
record Account(int id, String name) implements Runnable, Serializable
public record Account( int id, String name) {
public String nameAsUpperCase() {
return name().toUpperCase();
}
}
public record Account( int id, String name) {
public static String nameAsUpperCase(Account acc) {
return acc.name().toUpperCase();
}
}