Java Academy · Oppitunti

Record-tyypit, luokat ja Lombok

Vertaa record-tyyppejä perinteisiin luokkiin ja Lombok-annotaatioihin sopivan työkalun valitsemiseksi.

Oppitunti 4/413 vaihetta

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ää muotoa getName()
  • 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 state

Milloin 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 (@NonFinal joissakin 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 module

Pikakysymys

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ää
Aloita maksutta

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

  1. Record-tyyppien esittely
  2. Tiiviit konstruktorit ja validointi
  3. Mukautetut metodit record-tyypeissä
  4. Record-tyypit, luokat ja Lombok
← Takaisin: Java Academy