Record-tyypit, luokat ja Lombok
Vertaa record-tyyppejä perinteisiin luokkiin ja Lombok-annotaatioihin sopivan työkalun valitsemiseksi.
Record-tyypit, luokat ja Lombok on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Java Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Java Academy-kurssilla on yhteensä 4 oppituntia.
Recordit vs. luokat vs. Lombok
Java tarjoaa useita tapoja luoda dataa kuljettavia tyyppejä: vakiokoodia sisältävät tavalliset luokat, recordit (Java 16+) tai Lombok-annotaatiot. Oikea valinta riippuu käyttötapauksesta.
Vakiokoodiongelma
Tavallinen Java-luokka yksinkertaista datan siirtämistä varten vaatii paljon vakiokoodia: konstruktorin, getterit, equals-, hashCode- ja toString-metodit — kaikki vain muutamaa kenttää varten.
// Traditional class — lots of boilerplate
class ProductOld {
private final String id;
private final String name;
private final double price;
public ProductOld(String id, String name, double price) {
this.id = id; this.name = name; this.price = price;
}
public String getId() { return id; }
public String getName() { return name; }
public double getPrice() { return price; }
@Override public boolean equals(Object o) { /* ... */ }
@Override public int hashCode() { /* ... */ }
@Override public String toString() { /* ... */ }
}Record-ratkaisu
Record tiivistää saman luokan yhteen riviin. Kääntäjä luo kaiken vakiokoodin automaattisesti.
// Record — one line, same functionality
record Product(String id, String name, double price) {}
// Usage is almost identical except accessors use component names (no get prefix)
Product p = new Product("P001", "Laptop", 999.99);
System.out.println(p.id()); // P001 (not getId())
System.out.println(p.name()); // Laptop
System.out.println(p.price()); // 999.99
System.out.println(p); // Product[id=P001, name=Laptop, price=999.99]Lombok @Data ja @Value
Lombok luo vakiokoodin käännösaikana annotaatioiden avulla. @Value luo recordien kaltaisen muuttumattoman luokan, kun taas @Data luo muuttuvan luokan.
// Lombok @Value — immutable (closest to record)
import lombok.Value;
@Value
public class LombokProduct {
String id;
String name;
double price;
// Lombok generates: all-args constructor, getters, equals, hashCode, toString
// Note: accessors follow getX() naming convention (getPrice(), not price())
}
// Lombok @Data — mutable
import lombok.Data;
@Data
public class MutableProduct {
private String id;
private String name;
private double price;
// Generates: getters, setters, equals, hashCode, toString, no-args constructor
}Keskeiset erot
Records-tyyppien, Lombokin @Value-annotaation ja tavallisten luokkien tärkeät erot:
- Aksessorien nimeäminen: Records käyttää muotoa
name(); Lombok käyttää muotoagetName() - Muuttuva vaihtoehto: Records-tyypit ovat aina muuttumattomia; Lombok tarjoaa muokattavuutta varten @Data-annotaation
- Perintä: Records-tyypit eivät voi periä luokkia; Lombok-luokat voivat
- Koontityökalun riippuvuus: Lombok edellyttää annotaatioprosessorin määrityksiä; Records on sisäänrakennettu ominaisuus
Milloin Records-tyyppejä kannattaa käyttää
Records-tyypit sopivat erinomaisesti seuraaviin tilanteisiin:
- Tyyppi toimii ensisijaisesti läpinäkyvänä tietokantajana (DTO, Value Object)
- Muuttumattomuus on suunnittelun lähtökohta
- Käytössä on Java 16 tai uudempi ja haluatte välttää riippuvuudet
- Tyyppi osallistuu hahmonsovitukseen (sealed + records)
// Perfect record use cases:
record Coordinates(double lat, double lon) {}
record JwtClaims(String subject, String role, long expiresAt) {}
record PageRequest(int page, int size, String sortBy) {}
record ErrorResponse(int code, String message, String path) {}
// These are all simple data carriers with no mutable stateMilloin Lombokia kannattaa käyttää
Lombokia kannattaa käyttää, kun:
- Tarvitsette muokattavia bean-olioita (esimerkiksi JPA-entiteettejä tai Springin konfiguraatioluokkia)
- Aksessorien nimeämisen on noudatettava JavaBeans-käytäntöä (
getX) yhteensopivuuden vuoksi - Tarvitsette
@Builder-annotaatiota monimutkaisten olioiden luomiseen - Tarvitaan osittaista muokattavuutta (
@NonFinaljoissakin kentissä)
// Lombok @Builder — great for complex object construction
import lombok.*;
@Builder
@Value
public class EmailMessage {
String to;
String from;
String subject;
String body;
List<String> attachments;
}
EmailMessage msg = EmailMessage.builder()
.to("user@example.com")
.from("noreply@app.com")
.subject("Welcome!")
.body("Thank you for signing up")
.attachments(List.of())
.build();Milloin tavallisia luokkia kannattaa käyttää
Tavalliset luokat ovat edelleen sopiva valinta, kun:
- Luokalla on yksinkertaista tietojen säilyttämistä monimutkaisempaa toimintaa
- Teidän on perittävä toinen luokka
- hashCode/equals-toiminnolle tarvitaan tarkka hallinta
- Tarvitaan kapseloitua muuttuvaa tilaa
// Plain class — when behavior dominates over data
class ShoppingCart {
private final List<CartItem> items = new ArrayList<>();
private final String customerId;
public ShoppingCart(String customerId) {
this.customerId = customerId;
}
public void addItem(CartItem item) { items.add(item); }
public void removeItem(String sku) { items.removeIf(i -> i.sku().equals(sku)); }
public double total() { return items.stream().mapToDouble(CartItem::lineTotal).sum(); }
public boolean isEmpty() { return items.isEmpty(); }
}Recordien ja luokkien yhdistäminen
Records-tyypit ja luokat toimivat saumattomasti yhdessä. Käyttäkää recordeja muuttumatonta tietoa varten luokissa, jotka hallitsevat muuttuvaa tilaa.
// Record for the immutable event data
record UserEvent(String userId, String action, java.time.Instant timestamp) {
public static UserEvent now(String userId, String action) {
return new UserEvent(userId, action, java.time.Instant.now());
}
}
// Class for the mutable event store
class EventLog {
private final List<UserEvent> events = new ArrayList<>();
public void record(String userId, String action) {
events.add(UserEvent.now(userId, action));
}
public List<UserEvent> eventsFor(String userId) {
return events.stream()
.filter(e -> e.userId().equals(userId)).toList();
}
}Records Spring Bootissa
Records-tyypit toimivat hyvin Spring Bootissa pyyntöjen ja vastausten runkoina. Springin Jackson-muunnin käsittelee ne vähäisillä määrityksillä.
// Spring Boot REST controller using records
import org.springframework.web.bind.annotation.*;
record CreateProductRequest(String name, double price, String category) {}
record ProductResponse(long id, String name, double price, String category) {}
@RestController
@RequestMapping("/api/products")
class ProductController {
@PostMapping
public ProductResponse create(@RequestBody CreateProductRequest req) {
// Jackson automatically deserializes JSON into the record
long id = productService.save(req);
return new ProductResponse(id, req.name(), req.price(), req.category());
}
}Suorituskykyvertailu
Kaikki kolme lähestymistapaa tuottavat yksinkertaisten tietokantajien tapauksessa olennaisesti saman tavukoodin. Suorituskyky on sama — valinta riippuu kehittäjäkokemuksesta ja vaatimuksista.
// All three compile to approximately equivalent bytecode:
// - Records: compiler-generated, always immutable
// - Lombok @Value: annotation-processor-generated, always immutable
// - Plain class: hand-written
// The key runtime difference:
// Records: accessor is a method matching field name (price() not getPrice())
// Lombok/Class: accessor follows JavaBeans (getPrice())
// Jackson compatibility:
// Records: work natively in Jackson 2.12+ with no config
// Lombok: work with @JsonProperty or jackson-databind-lombok modulePikakysymys
Mitä nimeämiskäytäntöä recordien aksessorit noudattavat?
Kertaus: Records, luokat ja Lombok
Keskeiset opit:
- Records luo automaattisesti konstruktorin, aksessorit (ilman get-etuliitettä), equals-, hashCode- ja toString-metodit
- Records-tyypit ovat aina muuttumattomia; käyttäkää tavallisia luokkia muuttuvaa tilaa varten
- Lombokin @Value jäljittelee recordeja, mutta käyttää getX()-nimeämistä ja edellyttää määrityksiä
- Lombokin @Builder soveltuu erinomaisesti monimutkaisten olioiden luomiseen, kun valinnaisia kenttiä on paljon
- Records-tyypit sopivat erinomaisesti DTO-tyypeiksi, arvo-olioiksi sekä API-pyyntöjen ja -vastausten rungoiksi
- Tavalliset luokat ovat edelleen paras vaihtoehto, kun toiminta on keskeisessä roolissa tai tarvitaan perintää
Opi Java tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 104
- Oppitunnit
- 374
Usein kysytyt kysymykset
Onko oppitunti ”Record-tyypit, luokat ja Lombok” ilmainen?
Kyllä – oppitunnin ”Record-tyypit, luokat ja Lombok” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Java Academy-kurssin, päivitä CoddyKit PROhon. Java Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”Record-tyypit, luokat ja Lombok”?
Vertaa record-tyyppejä perinteisiin luokkiin ja Lombok-annotaatioihin sopivan työkalun valitsemiseksi. Harjoittelet Java Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Java Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Java Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”Record-tyypit, luokat ja Lombok”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Java Academy-oppitunnilla?
Kyllä. Jokainen Java Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- Record-tyyppien esittely
- Tiiviit konstruktorit ja validointi
- Mukautetut metodit record-tyypeissä
- Record-tyypit, luokat ja Lombok