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.
GO TO FULL VERSION