Metodi di Accesso ai Campi di un Record in Java

Concetti Chiave
  • I record in Java forniscono automaticamente metodi getter per accedere ai campi.
  • È possibile creare metodi getter personalizzati per implementare logiche specifiche o lanciare eccezioni.
  • I getter devono essere dichiarati public e seguire le regole di accessibilità.
  • I record sono immutabili, quindi i getter non devono modificare i valori dei campi.

Creare Metodi Getter per Record

Sebbene sia raramente necessario, è possibile creare la propria implementazione di un metodo getter di un record, ossia di un metodo di accesso ai campi di un record.

Quando si dichiara un getter, la versione implicita non viene più fornita. Un possibile motivo per cui si potrebbe voler dichiarare il proprio getter è lanciare un'eccezione se una certa condizione non è soddisfatta. Ad esempio, se un record contiene un nome file e un URL, il getter per il nome file potrebbe lanciare una FileNotFoundException se il file non è presente all'URL. C'è un requisito molto importante, tuttavia, che si applica alla creazione dei propri getter: devono aderire al principio che un record è immutabile. Pertanto, un getter che restituisce un valore alterato è semanticamente discutibile (e dovrebbe essere evitato) anche se tale codice sarebbe sintatticamente corretto.

Se si dichiara un'implementazione di getter, ci sono diverse regole che si applicano. Un getter deve avere lo stesso tipo di ritorno e nome del componente che ottiene. Deve anche essere esplicitamente dichiarato public. Pertanto, l'accessibilità predefinita non è sufficiente per una dichiarazione di getter in un record. Nessuna clausola throws è consentita in una dichiarazione di getter. Infine, un getter deve essere non generico e non-static.

Un'alternativa migliore al sovrascrivere un getter nei casi in cui si vuole ottenere un valore modificato di un componente è dichiarare un metodo separato con il suo nome. Ad esempio, assumendo il record Impiegato visto nelle lezioni precedenti, si potrebbe voler ottenere solo il cognome dal componente nome. Usare il getter standard per fare questo comporterebbe modificare il valore ottenuto dal componente. Fare questo è una cattiva idea perché violerebbe l'aspetto di immutabilità del record. Tuttavia, si potrebbe dichiarare un altro metodo, chiamato cognome(), che restituisce solo il cognome. Il seguente programma dimostra questo approccio. Usa anche il costruttore di controllo formato dalla lezione precedente per assicurarsi che i nomi siano memorizzati nel formato "nome cognome":

// Dichiara un record impiegato.
record Impiegato(String nome, int numeroId) {

    // Usa un campo static in un record.
    static int idInSospeso = -1;

    // Costruttore canonico compatto.
    public Impiegato {
        // Rimuove eventuali spazi iniziali e finali.
        nome = nome.trim();

        // Esegue una verifica minima per il formato del nome.
        // 1. Controlla che il nome non sia vuoto.
        // 2. Controlla che ci sia almeno uno spazio tra nome e cognome.
        // 3. Controlla che ci sia almeno un carattere (diverso dallo spazio)
        //    prima e dopo lo spazio.
        if (nome.isEmpty())
            throw new IllegalArgumentException("Il nome non può essere vuoto.");

        if (!nome.contains(" ")
                || nome.indexOf(" ") == 0
                || nome.indexOf(" ") == nome.length() - 1) {
            throw new IllegalArgumentException("Il nome deve essere nel formato 'nome cognome'.");
        }
    }

    // Questo è un metodo getter per ottenere
    // il cognome dal nome completo.
    public String cognome() {
        // Trova l'indice dello spazio nel nome.
        int spazioIndex = nome.indexOf(" ");
        // Restituisce il cognome, che è la parte dopo lo spazio.
        return nome.substring(spazioIndex + 1);
    }

}

class DemoRecord {

    public static void main(String[] args) {

        // Crea un array di record Impiegato.
        Impiegato[] listaImp = new Impiegato[4];

        // Crea una lista di impiegati che usa il record Impiegato.
        // Notate come ogni record è costruito. Gli argomenti
        // sono automaticamente assegnati ai campi nome e numeroId nel
        // record che sta essere creato.
        listaImp[0] = new Impiegato("Giovanni Rossi          ", 1047);
        listaImp[1] = new Impiegato("  Michele Verdi  ", 1048);
        listaImp[2] = new Impiegato("   Serena Bianchi  ", 1049);
        listaImp[3] = new Impiegato("    Silvia Neri", 1050);

        // Usa il metodo getter per stampare i cognomi e gli ID.
        for (Impiegato e : listaImp)
            System.out.println("L'ID impiegato per " + e.cognome() + " è " +
                                e.numeroId());
    }

}

L'output è mostrato qui:

L'ID impiegato per Rossi è 1047
L'ID impiegato per Verdi è 1048
L'ID impiegato per Bianchi è 1049
L'ID impiegato per Neri è 1050

Come mostra l'output, il getter implicito per il componente nome restituisce il nome inalterato. Il metodo di istanza cognome() ottiene solo il cognome. Con questo approccio, l'attributo immutabile del record Impiegato è preservato, fornendo ancora un mezzo conveniente per ottenere il cognome.