Inferenza Automatica dei Tipi e Riferimenti in Java

Concetti Chiave
  • A partire da JDK 10, Java supporta l'inferenza del tipo per le variabili locali utilizzando var.
  • L'inferenza del tipo semplifica la dichiarazione delle variabili, specialmente con tipi di riferimento, riducendo la verbosità del codice.
  • L'inferenza del tipo può essere utilizzata con tipi primitivi e tipi di riferimento, inclusi quelli definiti dall'utente.
  • È importante usare l'inferenza del tipo con saggezza per mantenenere la leggibilità del codice, evitando dichiarazioni ambigue.

Inferenza del Tipo delle Variabili Locali con Tipi di Riferimento

Come visto nella lezione apposita, a partire da JDK 10, Java supporta l'inferenza del tipo per le variabili locali.

Si ricorda che quando si utilizza l'inferenza del tipo per le variabili locali, il tipo della variabile è specificato con var e la variabile deve essere inizializzata. Abbiamo visto l'inferenza del tipo in azione con tipi primitivi, ma può essere usata anche con tipi di riferimento.

Infatti, l'inferenza del tipo con tipi di riferimento costituisce un uso primario. Ecco un semplice esempio che dichiara una variabile String chiamata miaStr:

var miaStr = "Questa è una stringa";

Poiché viene usata una stringa tra virgolette come inizializzatore, il tipo String viene inferito.

Come spiegato in precedenza, uno dei vantaggi dell'inferenza del tipo delle variabili locali è la sua capacità di semplificare il codice, ed è con i tipi di riferimento che tale semplificazione risulta più evidente.

La ragione di ciò è che molti tipi di classi in Java hanno nomi piuttosto lunghi. Ad esempio, quando studieremo l'I/O in Java, vedremo la classe FileInputStream, che viene usata per aprire un file per operazioni di input.

In passato, si sarebbe dichiarato e inizializzato un FileInputStream usando una dichiarazione tradizionale come quella mostrata qui:

FileInputStream fileIn = new FileInputStream("testo.txt");

Con l'uso di var, può ora essere scritta così:

var fileIn = new FileInputStream("testo.txt");

Qui, fileIn viene inferito come di tipo FileInputStream perché quello è il tipo dell'inizializzatore.

Non è necessario ripetere esplicitamente il nome del tipo. Di conseguenza, questa dichiarazione di fileIn è sostanzialmente più breve rispetto a quella tradizionale. In questo modo, l'uso di var semplifica la dichiarazione.

Questo beneficio diventa ancora più evidente in dichiarazioni più complesse, come quelle che coinvolgono i tipi generici. In generale, l'attributo di semplificazione dell'inferenza del tipo delle variabili locali aiuta a ridurre la noia dell'inserimento di nomi di tipo lunghi nel programma.

Nota

Attenzione alla leggibilità del codice

Ovviamente, l'aspetto di semplificazione dell'inferenza del tipo delle variabili locali deve essere utilizzato con cautela per evitare di ridurre la leggibilità del programma e, di conseguenza, oscurarne il significato. Ad esempio, si consideri una dichiarazione come quella mostrata qui:

var x = o.getNext();

In questo caso, potrebbe non essere immediatamente chiaro a qualcuno che legge il codice quale sia il tipo di x. In sostanza, l'inferenza del tipo delle variabili locali è una caratteristica che dovrebbe essere usata con saggezza.

Come ci si aspetterebbe, è possibile usare l'inferenza del tipo anche con classi definite dall'utente, come illustra il programma seguente. Crea una classe chiamata MiaClasse e quindi usa l'inferenza del tipo per dichiarare e inizializzare un oggetto di quella classe.

// Inferenza del tipo locale con un tipo di classe definita dall'utente.
class MiaClasse {
    private int i;

    MiaClasse(int k) { i = k; }

    int prendiI() { return i; }
    void impostaI(int k) { if(k >= 0) i = k; }
}

class RifVarDemo {
    public static void main(String[] args) {
        var mc = new MiaClasse(10); // Notare l'uso di var qui.

        System.out.println("Valore di i in mc è " + mc.prendiI());
        mc.impostaI(19);
        System.out.println("Valore di i in mc è ora " + mc.prendiI());
    }
}

L'output del programma è mostrato qui:

Valore di i in mc è 10
Valore di i in mc è ora 19

Nel programma, prestare particolare attenzione a questa riga:

var mc = new MiaClasse(10); // Notare l'uso di var qui.

Qui, il tipo di mc sarà inferito come MiaClasse perché quello è il tipo dell'inizializzatore, che è un nuovo oggetto MiaClasse.