back to top

Java: i modificatori final e static

Abbiamo fino a questo momento parlato degli aspetti principali della programmazione ad oggetti in Java. Prima di analizzare l’ultima parte di questo argomento, cioè le interfacce, è bene capire l’effetto che i modificatori final e static hanno nei vari contesti in cui sono utilizzati.

Il modificatore final

Il modificatore final è semplice da comprendere, poiché le implementazioni possibili sono legate alla sua traduzione letterale: finale o non mutabile. La sua funzione principale è quella di limitare la modificabilità delle variabili, dei metodi e delle classi.

Pubblicità

Dunque, il modificatore final può essere utilizzato per definire una variabile che diverrà una costante per l’istanza della classe. È importante notare che final può essere applicato anche ai metodi di una determinata classe. Un metodo definito come final implica che, se ereditiamo la classe che contiene il metodo, non sarà possibile eseguire l’override. Inoltre, se una classe è dichiarata come final, impediamo la sua estensione. Questo è logicamente comprensibile, poiché una classe dichiarata con il modificatore final è concepita per essere completa e non necessita di specializzazioni o estensioni.

Il modificatore static

Il modificatore static è un concetto più complesso, ma estremamente potente. Iniziamo con il dire che il modificatore static può essere applicato sia a metodi che a variabili di una classe. L’effetto di dichiarare un metodo static è quello di rendere il metodo comune a tutte le istanze della classe.

Per capire meglio il concetto, pensiamo a tutte le funzioni matematiche che Java ci mette a disposizione attraverso la classe Math. Ad esempio, la classe Math offre il metodo max, che restituisce il massimo tra due interi. Possiamo utilizzarlo con il seguente codice:

Math.max(3, 4);

La chiamata del metodo è diversa da quanto visto finora: non abbiamo istanziato la classe Math, né abbiamo richiamato il metodo max utilizzando la sintassi nomeOggetto.nomeMetodo(). Questo è possibile perché possiamo richiamare il metodo statico con la sintassi nomeClasse.nomeMetodo(). L’uso di static consente di evitare di istanziare la classe, preservando l’invariabilità dei suoi metodi. Per esempio, il valore massimo tra 3 e 4 sarà sempre 4; nulla potrà modificare tale relazione. È consigliabile utilizzare il modificatore static con parsimonia e solo se applicabile al concetto di uniformità delle funzionalità.

Esaminiamo ora cosa succede quando utilizziamo il modificatore static su una variabile di istanza. In questo caso, l’attributo della classe diventa comune a tutte le istanze. Consideriamo un esempio pratico con una semplice classe Prova contenente un solo attributo statico:

public class Prova {
  public static int numero;
}

La classe di implementazione per il nostro esempio sarà:

public class Implementazione {
  public static void main(String[] args) {
    Prova prova1 = new Prova();
    Prova prova2 = new Prova();
    prova1.numero = 10;
    System.out.println("Il valore numero per l'istanza 1 è: " + prova1.numero);
    System.out.println("Il valore numero per l'istanza 2 è: " + prova2.numero);
  }
}

L’output dell’esecuzione della classe Implementazione sarà:

Il valore numero per l'istanza 1 è: 10
Il valore numero per l'istanza 2 è: 10;

In sintesi, se dichiariamo una variabile di istanza utilizzando il costrutto public static, otteniamo una variabile globale accessibile da tutte le istanze di una classe. Sebbene le variabili globali offrano il vantaggio di condividere lo stesso valore tra tutte le istanze, comportano anche dei rischi. Qualora un’istanza modifichi la variabile globale, tutte le altre istanze della classe vedranno il valore aggiornato, ciò compromette la robustezza e l’integrità dell’intera applicazione.

Pubblicità