CodeGym /Cours /JAVA 25 SELF /Initialisation des champs statiques et final

Initialisation des champs statiques et final

JAVA 25 SELF
Niveau 15, Leçon 3
Disponible

1. Champs statiques : comment les initialiser ?

Un champ statique (static) n’appartient pas à un objet mais à la classe entière. Sa valeur n’existe qu’en un seul exemplaire pour tous les objets de cette classe. Par analogie — c’est comme la déclaration d’une « caisse commune » pour tous les employés d’une entreprise : peu importe qui arrive, la caisse est unique pour tous.

Initialisation lors de la déclaration

La façon la plus simple et la plus courante d’initialiser un champ statique est de lui affecter une valeur directement lors de sa déclaration :

public class User {
    private static int userCount = 0; // initialisation ici même

    // ... reste du code
}

Un tel champ sera initialisé lors du premier chargement de la classe User en mémoire.

Initialisation dans un bloc statique

Parfois, une logique d’initialisation plus complexe est nécessaire — par exemple, charger des données depuis un fichier ou effectuer des calculs. Dans ce cas, on utilise un bloc d’initialisation statique :

public class Config {
    public static String configPath;

    static {
        // Ce bloc s’exécutera UNE seule fois au chargement de la classe
        configPath = System.getenv("APP_CONFIG_PATH");
        if (configPath == null) {
            configPath = "/etc/app/default.conf";
        }
        System.out.println("Config path initialisé: " + configPath);
    }
}

Quand le bloc statique est-il exécuté ?

  • Lors du premier accès à la classe (par exemple, à la création du premier objet ou à l’appel de n’importe quelle méthode/variable statique).
  • Il s’exécute une seule fois pour chaque classe.

Particularités d’accès aux champs statiques

  • On accède aux champs statiques via le nom de la classe : User.userCount.
  • On peut aussi y accéder via un objet, mais c’est considéré comme une mauvaise pratique (cela embrouille le lecteur du code).

Exemple :

User u1 = new User();
User u2 = new User();
System.out.println(User.userCount); // correct
System.out.println(u1.userCount);   // fonctionne, mais déconseillé !

2. Champs final : quand et comment les initialiser ?

final est un modificateur qui signifie : « Ce champ ne peut être affecté qu’une seule fois, et ensuite il ne change plus ». Après initialisation, la valeur du champ devient immuable : pour un objet — c’est sa propriété fixe, et pour une classe (si le champ est statique) — une constante partagée.

Exemples d’utilisation :

  • Constantes (par exemple, PI).
  • Identifiant unique d’un objet, qui ne peut pas être modifié après sa création.

Exigences d’initialisation des champs final

En Java, il existe une règle stricte : chaque champ final doit obligatoirement être initialisé soit lors de la déclaration, soit dans chacun des constructeurs de la classe.

Initialisation lors de la déclaration

public class Circle {
    public static final double PI = 3.1415926535; // constante de classe
    private final String id = "CIRCLE";           // constante d’objet
}

Initialisation dans le constructeur

Parfois, la valeur d’un champ final n’est connue qu’au moment de la création de l’objet :

public class User {
    private final int id;

    public User(int id) {
        this.id = id; // affectation du champ final dans le constructeur
    }
}

Important : si la classe a plusieurs constructeurs, le champ final doit être initialisé dans chacun d’eux !

Exemple combiné

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

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

Erreurs de compilation en cas de mauvaise initialisation

Si vous oubliez d’initialiser un champ final, le compilateur refusera de construire le programme :

public class Broken {
    private final int x; // non initialisé

    public Broken() {
        // x n’est pas affecté !
    }
}
// Erreur: variable x might not have been initialized

3. Combinaison de static et final : déclaration de constantes de classe

On rencontre très souvent le trio public static final. En Java, on déclare ainsi des constantes de classe — des valeurs définies une fois pour toutes et qui ne changent pas pendant l’exécution du programme. Ces constantes appartiennent à la classe entière et sont identiques pour tous ses objets.

Syntaxe et exemple

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

Explication :

  • public — accessible partout.
  • static — appartient à la classe entière, et non à un objet particulier.
  • final — ne peut pas être modifié après initialisation.

Utilisation

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

Convention : les noms de constantes s’écrivent généralement en MAJUSCULES_AVEC_UN_TIRET_BAS.

4. Exemples de code : variantes d’initialisation des champs statiques et final

Exemple 1 : classe simple avec une constante

public class Constants {
    public static final int DAYS_IN_WEEK = 7;
    public static final String COMPANY = "SARL Camomille";
}

Exemple 2 : champ statique initialisé dans un bloc statique

public class AppConfig {
    public static final String DEFAULT_PATH;

    static {
        // On peut exécuter une logique complexe
        String env = System.getenv("APP_PATH");
        if (env != null) {
            DEFAULT_PATH = env;
        } else {
            DEFAULT_PATH = "/usr/local/app";
        }
    }
}

Exemple 3 : champ final d’objet, initialisation dans le constructeur

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; 
    }
}

Utilisation :

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

Exemple 4 : erreur lors d’une mauvaise initialisation d’un champ final

public class BadExample {
    private final int number;

    public BadExample() {
        // number non initialisé !
    }
}
// Erreur de compilation: variable number might not have been initialized

5. Bonnes pratiques avec les champs statiques et final

Utilisez public static final uniquement pour de vraies constantes

Si la valeur peut changer à l’avenir (par exemple, une liste d’employés), ne la déclarez pas final ! Les constantes doivent être réellement immuables.

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

Bien que la référence USERS elle-même ne change pas, le contenu du tableau peut être modifié. Cela peut conduire à des erreurs inattendues.

Pour une initialisation complexe, utilisez des blocs statiques

Si une constante ne peut pas être exprimée par une simple affectation (par exemple, un calcul ou une lecture de fichier est nécessaire), utilisez un bloc statique.

N’abusez pas des champs statiques

Les champs statiques — ce sont des variables globales. En avoir trop peut entraîner des bugs difficiles à traquer et un code difficile à maintenir.

Ne rendez pas des objets mutables public static final

Si un objet est mutable, ne le rendez pas public et final. Cela ouvrira l’accès à ses entrailles pour tout le monde, et quelqu’un finira forcément par en abuser.

6. Erreurs typiques lors de l’initialisation des champs statiques et final

Erreur n° 1 : champ final non initialisé. Si vous oubliez d’initialiser un champ final soit lors de la déclaration, soit dans tous les constructeurs, le compilateur émettra une erreur. Par exemple, si la classe a deux constructeurs et que dans l’un d’eux vous oubliez d’affecter une valeur au champ final — il y aura une erreur.

Erreur n° 2 : modification de la valeur d’un champ final. Tenter de modifier la valeur d’un champ final après son initialisation entraînera une erreur de compilation.

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

Erreur n° 3 : champs static final publics et mutables. Si vous rendez un objet mutable (String[], int[], etc.) public static final, n’importe quel code pourra en modifier le contenu. Cela viole l’encapsulation et peut mener à des bugs difficiles à reproduire.

Erreur n° 4 : utilisation de champs non statiques dans un bloc statique. Dans un bloc statique, on ne peut pas accéder à des champs non statiques, parce qu’ils ne sont pas encore initialisés (et n’existent tout simplement pas à ce stade).

Erreur n° 5 : ordre d’initialisation inattendu. Si, dans un bloc statique, vous accédez à des champs statiques déclarés plus bas dans le code, ils peuvent ne pas encore être initialisés. Déclarez toujours les champs statiques avant les blocs statiques si vous prévoyez de les utiliser.

1
Mission
JAVA 25 SELF, niveau 15, leçon 3
Bloqué
Compteur global d'utilisateurs actifs 🌐
Compteur global d'utilisateurs actifs 🌐
1
Mission
JAVA 25 SELF, niveau 15, leçon 3
Bloqué
Nom immuable sur la carte d'étudiant 📝
Nom immuable sur la carte d'étudiant 📝
1
Mission
JAVA 25 SELF, niveau 15, leçon 3
Bloqué
Détermination de la langue de démarrage de l'application ⚙️
Détermination de la langue de démarrage de l'application ⚙️
1
Mission
JAVA 25 SELF, niveau 15, leçon 3
Bloqué
Constantes fondamentales pour les calculs ⚛️
Constantes fondamentales pour les calculs ⚛️
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION