CodeGym /Corsi /JAVA 25 SELF /Record con metodi

Record con metodi

JAVA 25 SELF
Livello 22 , Lezione 3
Disponibile

1. Estensione della classe record: metodi aggiuntivi

Si possono aggiungere metodi in un record?

Certo! Un Record è come un appartamento già ristrutturato: muri e pavimento sono pronti, non si possono cambiare, ma nessuno vieta di disporre i mobili come si vuole. All’interno di un record si possono dichiarare metodi normali, metodi statici e persino conservare costanti. Questo significa che la logica di business non è obbligatorio spostarla in classi «di utilità» — la si può integrare con cura direttamente nel record.

Esempio: metodo di calcolo della distanza tra punti

Supponiamo di avere un record per un punto sul piano:


public record Point(int x, int y) {
    // Metodo aggiuntivo
    public double distanceTo(Point other) {
        int dx = this.x - other.x;
        int dy = this.y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

Ora si può fare così:


Point p1 = new Point(0, 0);
Point p2 = new Point(3, 4);
System.out.println(p1.distanceTo(p2)); // 5.0

Come si vede, la classe record si può «arricchire» con metodi propri — ed è molto comodo!

Esempio: metodo statico


public record Rectangle(int width, int height) {
    public int area() {
        return width * height;
    }

    public static Rectangle square(int size) {
        return new Rectangle(size, size);
    }
}

Ora si può creare un «quadrato» con una sola chiamata:


Rectangle r = Rectangle.square(5);
System.out.println(r.area()); // 25

2. Costruttore compatto e validazione dei dati

A cosa serve il costruttore «compatto»?

Il costruttore canonico del record viene creato automaticamente e assegna i parametri ai campi. Ma a volte si vuole aggiungere un controllo degli input (per esempio, vietare coordinate negative).

In una classe normale scriveremmo:


public class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        if (x < 0 || y < 0) throw new IllegalArgumentException();
        this.x = x;
        this.y = y;
    }
    // ...
}

In una classe record si può dichiarare un costruttore compatto — senza ripetere la lista dei parametri e senza l’assegnazione esplicita dei campi (lo fa il compilatore per noi).

Sintassi del costruttore compatto


public record Point(int x, int y) {
    public Point {
        if (x < 0 || y < 0) {
            throw new IllegalArgumentException("Coordinates must be non-negative");
        }
        // Non serve scrivere: this.x = x; this.y = y;
    }
}
  • I parametri del costruttore corrispondono automaticamente ai componenti del record.
  • L’assegnazione this.x = x e this.y = y è effettuata dal compilatore automaticamente dopo l’esecuzione del corpo del costruttore (o dopo l’uscita riuscita da esso).
  • Se viene lanciata un’eccezione, l’oggetto non verrà creato.

Esempio con verifica


Point p1 = new Point(3, 5); // OK
Point p2 = new Point(-1, 2); // Genererà IllegalArgumentException!

Si può dichiarare un costruttore «normale»?

Sì, si può! Se serve creare un costruttore con un’altra lista di parametri o logica aggiuntiva, dichiaratelo esplicitamente:


public record Range(int from, int to) {
    public Range(int size) {
        this(0, size); // chiama il costruttore principale
    }
}

3. Limitazioni delle classi record

A differenza delle classi normali, le classi record hanno una serie di limitazioni. È importante ricordarlo per non sorprendersi degli errori di compilazione.

Solo componenti — nessun campo non statico aggiuntivo

In una classe record non si possono dichiarare nuovi campi non statici:


public record Person(String name, int age) {
    // int id; // Errore di compilazione! Non è consentito aggiungere campi non statici.
}

Si possono dichiarare campi e metodi statici:


public record Person(String name, int age) {
    public static final String SPECIES = "Homo sapiens";
}

I record sono sempre final

Una classe Record non può essere classe genitore (non si può ereditarne) e non può estendere esplicitamente un’altra classe (tranne l’ereditarietà implicita da java.lang.Record). Ciò significa che una classe record è sempre una struttura «finale».


public record User(String login) { }

// public class Admin extends User {} // Errore: non si può estendere un record!

Si possono implementare interfacce

Una classe Record può implementare interfacce:


public interface Printable {
    void print();
}

public record Invoice(int amount) implements Printable {
    @Override
    public void print() {
        System.out.println("Importo: " + amount);
    }
}

4. Esempi: record estesi in casi reali

Vediamo alcuni esempi pratici in cui metodi aggiuntivi e costruttori compatti rendono la classe record davvero utile.

Record con un metodo di calcolo


public record Circle(double x, double y, double radius) {
    public double area() {
        return Math.PI * radius * radius;
    }

    public double distanceTo(Circle other) {
        double dx = x - other.x;
        double dy = y - other.y;
        return Math.sqrt(dx * dx + dy * dy);
    }
}

Record con validazione


public record Email(String value) {
    public Email {
        if (value == null || !value.contains("@")) {
            throw new IllegalArgumentException("Email non valida: " + value);
        }
    }
}

Ora non si può creare un'email non valida:


Email e1 = new Email("test@example.com"); // OK
Email e2 = new Email("not-an-email"); // Genererà IllegalArgumentException

Record con metodi statici aggiuntivi


public record Temperature(double celsius) {
    public static Temperature fromFahrenheit(double fahrenheit) {
        return new Temperature((fahrenheit - 32) * 5 / 9);
    }

    public double toFahrenheit() {
        return celsius * 9 / 5 + 32;
    }
}

Utilizzo:


Temperature t = Temperature.fromFahrenheit(98.6);
System.out.println(t.celsius()); // 37.0
System.out.println(t.toFahrenheit()); // 98.6

5. Costruttore compatto: sfumature e limitazioni

Quando usare il costruttore compatto?

  • Se serve verificare la correttezza dei dati (validazione).
  • Se è necessario modificare i valori prima di memorizzarli (per esempio, arrotondare un numero o portare una stringa in maiuscolo).
  • Se si vuole evitare di duplicare l’elenco dei parametri.

Caratteristiche di funzionamento

  • Nel costruttore compatto non si possono assegnare esplicitamente valori ai componenti (this.x = ...) — questo genererà un errore di compilazione, perché il compilatore esegue l’assegnazione dopo l’esecuzione del corpo del costruttore.
  • Nel costruttore compatto non si possono cambiare i nomi dei parametri — corrispondono sempre ai nomi dei componenti del record.

Esempio: arrotondamento automatico


public record Money(double amount) {
    public Money {
        amount = Math.round(amount * 100) / 100.0; // Arrotondiamo ai centesimi
    }
}

6. Pratica: sviluppiamo un’applicazione didattica

Supponiamo di effettuare operazioni bancarie in un’applicazione didattica. Abbiamo una classe record Transaction, che memorizza l’importo, il mittente e il destinatario.


public record Transaction(String from, String to, double amount) {
    public Transaction {
        if (amount <= 0) throw new IllegalArgumentException("L'importo deve essere positivo");
        if (from == null || to == null) throw new IllegalArgumentException("I campi non possono essere null");
    }

    public String description() {
        return String.format("Trasferimento %.2f da %s a %s", amount, from, to);
    }
}

Utilizzo:


Transaction t = new Transaction("Alice", "Bob", 150.0);
System.out.println(t.description()); // Trasferimento 150.00 da Alice a Bob

Un tentativo di creare una transazione non valida provocherà un errore:


Transaction t2 = new Transaction("Alice", "Bob", -10.0); // IllegalArgumentException

Tabella: cosa si può e cosa non si può in una classe record

Consentito in una classe record Vietato in una classe record
Metodi normali Nuovi campi non statici
Metodi e campi statici Ereditare da altre classi
Implementare interfacce Essere superclasse per altri
Costruttori compatti e normali Modificare i componenti dopo la creazione
Sovrascrivere metodi Usare setter

7. Errori tipici nel lavoro con le classi record con corpo non standard

Errore № 1: tentativo di aggiungere un campo non statico.
I principianti spesso cercano di aggiungere a una classe record «un altro campo per la logica interna» — per esempio, un contatore o una cache. Non funzionerà: il compilatore restituirà subito un errore. Se avete bisogno di conservare stato aggiuntivo, molto probabilmente la classe record non è la scelta giusta.

Errore № 2: dimenticata la validazione nel costruttore compatto.
Se volete che l’oggetto sia sempre valido, eseguite i controlli nel costruttore compatto. Non fate affidamento sul fatto che «l’utente non inserirà sciocchezze».

Errore № 3: tentativo di modificare un componente dopo la creazione.
I campi della classe record sono final — non si possono modificare né direttamente, né tramite metodi. Se vi serve una struttura mutabile, usate una classe normale.

Errore № 4: duplicazione della logica nei metodi e nel costruttore.
A volte si tenta di duplicare la logica di controllo e quella di calcolo sia nei metodi sia nel costruttore. Meglio fare tutta la validazione nel costruttore e lasciare i metodi alla «pura» logica di business.

Errore № 5: dimenticate le limitazioni dell’ereditarietà.
Una classe Record è sempre final — non si può crearne un sottotipo. Se state progettando una gerarchia in cui servono sottoclassi, usate classi normali.

1
Compito
JAVA 25 SELF, livello 22, lezione 3
Bloccato
Letture del termometro alla stazione meteorologica 🌡️
Letture del termometro alla stazione meteorologica 🌡️
1
Compito
JAVA 25 SELF, livello 22, lezione 3
Bloccato
Validazione dell'indirizzo email durante la registrazione 📧
Validazione dell'indirizzo email durante la registrazione 📧
1
Compito
JAVA 25 SELF, livello 22, lezione 3
Bloccato
Creazione di una scheda personaggio con dati generali 🧍
Creazione di una scheda personaggio con dati generali 🧍
1
Compito
JAVA 25 SELF, livello 22, lezione 3
Bloccato
Registrazione delle transazioni finanziarie in banca 💸
Registrazione delle transazioni finanziarie in banca 💸
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION