CodeGym /Corsi /JAVA 25 SELF /Inizializzazione dei campi static e final

Inizializzazione dei campi static e final

JAVA 25 SELF
Livello 15 , Lezione 3
Disponibile

1. Campi static: come inizializzarli?

Un campo (static) non appartiene all’oggetto, ma all’intera classe. Il suo valore esiste in un’unica istanza per tutti gli oggetti di questa classe. Per analogia — è come dichiarare una «cassa comune» per tutti i dipendenti dell’azienda: non importa chi arrivi, la cassa è una per tutti.

Inizializzazione alla dichiarazione

Il modo più semplice e diffuso per inizializzare un campo static è assegnargli un valore direttamente nella dichiarazione:

public class User {
    private static int userCount = 0; // inizializzazione proprio qui

    // ... altro codice
}

Tale campo verrà inizializzato al primo caricamento in memoria della classe User.

Inizializzazione in un blocco statico

A volte serve una logica di inizializzazione più complessa — ad esempio, caricare dati da un file o eseguire calcoli. In questo caso si usa un blocco di inizializzazione statico:

public class Config {
    public static String configPath;

    static {
        // Questo blocco verrà eseguito UNA sola volta al caricamento della classe
        configPath = System.getenv("APP_CONFIG_PATH");
        if (configPath == null) {
            configPath = "/etc/app/default.conf";
        }
        System.out.println("Percorso di configurazione inizializzato: " + configPath);
    }
}

Quando viene eseguito un blocco statico?

  • Al primo accesso alla classe (ad esempio, alla creazione del primo oggetto o alla chiamata di qualsiasi metodo/campo statico).
  • Viene eseguito una sola volta per ogni classe.

Particolarità di accesso ai campi static

  • Si accede ai campi static tramite il nome della classe: User.userCount.
  • Si può anche accedervi tramite un oggetto, ma è considerato cattivo stile (confonde chi legge il codice).

Esempio:

User u1 = new User();
User u2 = new User();
System.out.println(User.userCount); // corretto
System.out.println(u1.userCount);   // funziona, ma sconsigliato!

2. Campi final: quando e come inizializzarli?

final è un modificatore che dice: «Questo campo può essere assegnato una sola volta e poi non cambierà». Dopo l’inizializzazione il valore del campo diventa immutabile: per l’oggetto è una sua proprietà fissa, e per la classe (se il campo è static) è una costante comune.

Esempi d’uso:

  • Costanti (ad esempio, PI).
  • Un identificativo univoco dell’oggetto che non si può cambiare dopo la creazione.

Requisiti per l’inizializzazione dei campi final

In Java c’è una regola rigorosa: ogni campo final deve essere inizializzato o alla dichiarazione, oppure in ciascun costruttore della classe.

Inizializzazione alla dichiarazione

public class Circle {
    public static final double PI = 3.1415926535; // costante della classe
    private final String id = "CIRCLE";           // costante dell’oggetto
}

Inizializzazione nel costruttore

Talvolta il valore di un campo final è noto solo al momento della creazione dell’oggetto:

public class User {
    private final int id;

    public User(int id) {
        this.id = id; // assegniamo il campo final nel costruttore
    }
}

Importante: se la classe ha più costruttori, il campo final deve essere inizializzato in ciascuno di essi!

Esempio combinato

public class Token {
    private final String value;
    private final long timestamp;

    public Token(String value) {
        this.value = value;
        this.timestamp = System.currentTimeMillis();
    }
}

Errori di compilazione in caso di inizializzazione errata

Se vi dimenticate di inizializzare un campo final, il compilatore non consentirà di costruire il programma:

public class Broken {
    private final int x; // non inizializzato

    public Broken() {
        // x non viene assegnato!
    }
}
// Errore: variable x might not have been initialized

3. Combinazione di static e final: dichiarazione di costanti di classe

Molto spesso si incontra la combinazione public static final. In Java così si dichiarano le costanti di classe — valori che vengono impostati una sola volta e non cambiano durante l’esecuzione del programma. Queste costanti appartengono all’intera classe e sono uguali per tutti i suoi oggetti.

Sintassi ed esempio

public class MathUtils {
    public static final double PI = 3.1415926535;
    public static final String APP_NAME = "MyApp";
}

Spiegazione:

  • public — accessibile ovunque.
  • static — appartiene alla classe, non al singolo oggetto.
  • final — non può essere modificato dopo l’inizializzazione.

Utilizzo

double area = MathUtils.PI * r * r;
System.out.println(MathUtils.APP_NAME);

Convenzione: i nomi delle costanti di solito si scrivono in MAIUSCOLO_CON_SOTTOLINEATURA.

4. Esempi di codice: varianti di inizializzazione di campi static e final

Esempio 1: classe semplice con costante

public class Constants {
    public static final int DAYS_IN_WEEK = 7;
    public static final String COMPANY = "OOO Romashka";
}

Esempio 2: campo static inizializzato in un blocco statico

public class AppConfig {
    public static final String DEFAULT_PATH;

    static {
        // Si può eseguire una logica complessa
        String env = System.getenv("APP_PATH");
        if (env != null) {
            DEFAULT_PATH = env;
        } else {
            DEFAULT_PATH = "/usr/local/app";
        }
    }
}

Esempio 3: campo final dell’oggetto, inizializzazione nel costruttore

public class User {
    private static int nextId = 1;
    private final int id;
    private String name;

    public User(String name) {
        this.id = nextId++;
        this.name = name;
    }

    public int getId() { 
        return id; 
    }
    public String getName() {
        return name; 
    }
    public void setName(String name) { 
        this.name = name; 
    }
}

Utilizzo:

User u1 = new User("Ivan");
User u2 = new User("Maria");
System.out.println(u1.getId()); // 1
System.out.println(u2.getId()); // 2

Esempio 4: errore con inizializzazione errata di un campo final

public class BadExample {
    private final int number;

    public BadExample() {
        // number non inizializzato!
    }
}
// Errore di compilazione: variable number might not have been initialized

5. Buone pratiche con campi static e final

Usate public static final solo per vere costanti

Se il valore può cambiare in futuro (ad esempio, l’elenco dei dipendenti), non rendetelo final! Le costanti devono essere veramente immutabili.

public static final int MAX_USERS = 1000; // bene
public static final String[] USERS = new String[100]; // male!

Sebbene il riferimento USERS non cambi, il contenuto dell’array può essere modificato. Questo può portare a errori inattesi.

Per un’inizializzazione complessa usate i blocchi statici

Se la costante non può essere espressa con una semplice assegnazione (ad esempio, serve un calcolo o la lettura da un file), usate un blocco statico.

Non abusate dei campi static

I campi static sono variabili globali. Un loro numero eccessivo può portare a errori difficili da individuare e a una manutenzione complicata del codice.

Non rendete pubblici e final gli oggetti mutabili

Se un oggetto è mutabile, non rendetelo pubblico e final. Questo esporrà il suo stato interno a tutti, e qualcuno sicuramente ne approfitterà.

6. Errori tipici nell’inizializzazione di campi static e final

Errore n. 1: Campo final non inizializzato. Se ci si dimentica di inizializzare un campo final alla dichiarazione oppure in tutti i costruttori, il compilatore emetterà un errore. Ad esempio, se la classe ha due costruttori e in uno di essi vi dimenticate di assegnare un valore al campo final — si verificherà un errore.

Errore n. 2: Modifica del valore di un campo final. Il tentativo di modificare il valore di un campo final dopo l’inizializzazione porterà a un errore di compilazione.

public class Demo {
    private final int x = 5;
    public void change() {
        x = 10; // Errore: cannot assign a value to final variable x
    }
}

Errore n. 3: Campi static final mutabili e pubblici. Se si rende un oggetto mutabile (String[], int[] ecc.) public static final, qualsiasi codice potrà cambiarne il contenuto. Questo viola l’incapsulamento e può portare a bug difficili da individuare.

Errore n. 4: Uso di campi non static in un blocco static. In un blocco static non si può accedere ai campi non static, perché non sono ancora inizializzati (e in questa fase non esistono affatto).

Errore n. 5: Ordine di inizializzazione inatteso. Se in un blocco static accedete a campi static dichiarati più in basso nel codice, è possibile che non siano ancora inizializzati. Dichiarate sempre i campi static prima dei blocchi statici se prevedete di usarli.

1
Compito
JAVA 25 SELF, livello 15, lezione 3
Bloccato
Contatore globale degli utenti attivi 🌐
Contatore globale degli utenti attivi 🌐
1
Compito
JAVA 25 SELF, livello 15, lezione 3
Bloccato
Nome immutabile sulla tessera studente 📝
Nome immutabile sulla tessera studente 📝
1
Compito
JAVA 25 SELF, livello 15, lezione 3
Bloccato
Determinazione della lingua iniziale dell'applicazione ⚙️
Determinazione della lingua iniziale dell'applicazione ⚙️
1
Compito
JAVA 25 SELF, livello 15, lezione 3
Bloccato
Costanti fondamentali per i calcoli ⚛️
Costanti fondamentali per i calcoli ⚛️
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION