Java Academy · Oppitunti

Record-tyyppien esittely

Määritä record-tyyppejä tiiviiksi muuttumattomiksi tietosäiliöiksi ja ymmärrä niiden automaattisesti luodut jäsenet.

Oppitunti 1/413 vaihetta

Record-tyyppien esittely on ilmainen Java Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/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.

Recordien esittely

Java-recordit (Java 16+) ovat tiivis tapa määritellä muuttumattomia dataa kuljettavia luokkia. Ne luovat automaattisesti vakiokoodin: konstruktorin, getterit, equals-, hashCode- ja toString-metodit.

Recordin määrittäminen

Käyttäkää record-avainsanaa, jota seuraavat recordin nimi ja komponenttiluettelo. Jokaisesta komponentista tulee private final -kenttä ja julkinen accessor-metodi.

record Point(double x, double y) {}

Point p = new Point(3.0, 4.0);
System.out.println(p.x());      // 3.0 (accessor, not getX())
System.out.println(p.y());      // 4.0
System.out.println(p);          // Point[x=3.0, y=4.0]
System.out.println(p.equals(new Point(3.0, 4.0))); // true

Automaattisesti luotavat jäsenet

Kääntäjä luo automaattisesti jokaiseen recordiin seuraavat jäsenet: kanonisen konstruktorin, julkiset accessor-metodit, equals(), hashCode() ja toString(). Näitä ei tarvitse kirjoittaa käsin.

record Product(String name, double price, int stock) {}

Product p1 = new Product("Widget", 9.99, 100);
Product p2 = new Product("Widget", 9.99, 100);

System.out.println(p1.name());          // Widget
System.out.println(p1.price());         // 9.99
System.out.println(p1.equals(p2));      // true (structural)
System.out.println(p1.hashCode() == p2.hashCode()); // true
System.out.println(p1);                 // Product[name=Widget, price=9.99, stock=100]

Recordit ovat muuttumattomia

Record-komponentit ovat final. Niitä ei voi muuttaa rakentamisen jälkeen — recordit mallintavat muuttumattomia arvo-objekteja.

record Money(long cents, String currency) {}

Money price = new Money(999, "USD");
// price.cents = 500; // Compile error — final field!

// To "update" a record, create a new one
Money discounted = new Money(price.cents() - 100, price.currency());
System.out.println(discounted); // Money[cents=899, currency=USD]

Recordit perivät vain Objectin

Recordit perivät implisiittisesti java.lang.Record-luokan eivätkä voi periä muita luokkia. Ne voivat toteuttaa rajapintoja.

interface Describable { String describe(); }

record Circle(double radius) implements Describable {
    public String describe() {
        return String.format("Circle with radius %.1f", radius);
    }

    public double area() {
        return Math.PI * radius * radius;
    }
}

Circle c = new Circle(5.0);
System.out.println(c.describe()); // Circle with radius 5.0
System.out.printf("Area: %.2f%n", c.area()); // Area: 78.54

Recordit kokoelmissa

Koska recordit toteuttavat equals- ja hashCode-metodit oikein kaikkien komponenttien perusteella, ne toimivat oikein Map-avaimina ja Set-alkioina.

import java.util.*;

record Coordinate(int row, int col) {}

Map<Coordinate, String> grid = new HashMap<>();
grid.put(new Coordinate(0, 0), "Origin");
grid.put(new Coordinate(1, 2), "Target");

// Lookup with equal-valued record works correctly
System.out.println(grid.get(new Coordinate(0, 0))); // Origin
System.out.println(grid.get(new Coordinate(1, 2))); // Target

Set<Coordinate> visited = new HashSet<>();
visited.add(new Coordinate(3, 3));
System.out.println(visited.contains(new Coordinate(3, 3))); // true

Recordit DTO:ina

Recordit sopivat erinomaisesti Data Transfer Objecteiksi (DTO:iksi) REST-rajapinnoissa — ne kuljettavat dataa kerrosten välillä ilman toiminnallisuutta.

record CreateUserRequest(String email, String displayName, String plan) {}

record UserResponse(long id, String email, String displayName,
                    String plan, String createdAt) {}

// Simulating a service call
static UserResponse createUser(CreateUserRequest req) {
    long id = 42L;
    return new UserResponse(id, req.email(), req.displayName(),
        req.plan(), java.time.Instant.now().toString());
}

CreateUserRequest req = new CreateUserRequest("alice@example.com", "Alice", "PRO");
UserResponse resp = createUser(req);
System.out.println(resp);

Recordien hajottaminen

Recordit sopivat hyvin yhteen hahmonsovituksen kanssa. Niitä voi hajottaa switch-lausekkeissa (Java 21+).

sealed interface Shape permits Circle, Rectangle, Triangle {}
record Circle(double radius) implements Shape {}
record Rectangle(double width, double height) implements Shape {}
record Triangle(double base, double height) implements Shape {}

static double area(Shape s) {
    return switch (s) {
        case Circle(double r)            -> Math.PI * r * r;
        case Rectangle(double w, double h) -> w * h;
        case Triangle(double b, double h) -> 0.5 * b * h;
    };
}

System.out.printf("%.2f%n", area(new Circle(5)));         // 78.54
System.out.printf("%.2f%n", area(new Rectangle(4, 6)));   // 24.00

Recordien serialisointi

Recordit toteuttavat Serializable-rajapinnan luontevasti, kun ne määritellään toteuttamaan se. Ne toimivat JSON-kirjastojen, kuten Jacksonin ja Gsonin, kanssa heti käyttövalmiina.

// With Jackson (add @JsonProperty if needed)
import com.fasterxml.jackson.databind.ObjectMapper;

record OrderSummary(String orderId, double total, String status) {}

ObjectMapper mapper = new ObjectMapper();
OrderSummary order = new OrderSummary("ORD-001", 149.99, "SHIPPED");

String json = mapper.writeValueAsString(order);
System.out.println(json);
// {"orderId":"ORD-001","total":149.99,"status":"SHIPPED"}

OrderSummary restored = mapper.readValue(json, OrderSummary.class);
System.out.println(order.equals(restored)); // true

Sisäkkäiset recordit

Recordit voivat sisältää muita recordeja komponentteina, jolloin voidaan rakentaa rikkaita muuttumattomia objektirakenteita.

record Address(String street, String city, String country) {}
record Customer(long id, String name, Address address) {}

Address addr = new Address("123 Main St", "New York", "US");
Customer customer = new Customer(1L, "Alice", addr);

System.out.println(customer.name());              // Alice
System.out.println(customer.address().city());   // New York
System.out.println(customer);                    // Customer[id=1, name=Alice, address=Address[street=123 Main St, city=New York, country=US]]

Recordien rajoitukset

Recordeihin liittyy rajoituksia, jotka on hyvä tuntea:

  • Muita luokkia ei voi periä (recordit perivät implisiittisesti Recordin)
  • Komponentit ovat aina final — muuttuvaa tilaa ei ole
  • Ilmentymäkenttiä ei voi määritellä komponenttiluettelon ulkopuolelle
  • Recordit eivät voi olla abstract
// Records CAN have static fields and methods
record Temperature(double celsius) {
    static final double ABSOLUTE_ZERO = -273.15;

    public double toFahrenheit() {
        return celsius * 9.0/5.0 + 32;
    }

    public static Temperature fromFahrenheit(double f) {
        return new Temperature((f - 32) * 5.0/9.0);
    }
}
System.out.println(Temperature.fromFahrenheit(98.6)); // Temperature[celsius=37.0]

Pikatarkistus

Mitkä jäsenet Java-kääntäjä luo automaattisesti recordille?

Kertaus: recordien esittely

Tärkeimmät opit:

  • Recordeilla voi määritellä muuttumattomia dataa kuljettavia olioita vähäisellä vakiokoodilla
  • Automaattisesti luodaan kanoninen konstruktori, accessor-metodit, equals, hashCode ja toString
  • Komponentit ovat final — recordit ovat suunnitellusti muuttumattomia
  • Recordit voivat toteuttaa rajapintoja, mutta eivät voi periä luokkia
  • Ne sopivat erinomaisesti DTO:iksi, arvo-objekteiksi ja API-vastauksiksi
  • Ne toimivat oikein HashMapin avaimina ja HashSetin alkioina rakenteellisen yhtäsuuruuden ansiosta
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-tyyppien esittely” ilmainen?

Kyllä – oppitunnin ”Record-tyyppien esittely” 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-tyyppien esittely”?

Määritä record-tyyppejä tiiviiksi muuttumattomiksi tietosäiliöiksi ja ymmärrä niiden automaattisesti luodut jäsenet. 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 1/4.

Kuinka kauan ”Record-tyyppien esittely”-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