Qu'est-ce qu'une "classe statique" en Java ? Explications et exemples
\n\nSi vous avez déjà écrit du code Java, vous avez probablement croisé la mystérieuse construction static class. « Comment ça ? — demanderez-vous. — static est un modificateur pour les champs et les méthodes, pas pour les classes ! » Et vous auriez raison… presque.
En réalité, Java n'a pas de « classes statiques » au sens où il a des variables ou méthodes statiques. Mais il existe des classes imbriquées statiques (static nested classes). Et c'est l'une des fonctionnalités les plus sous-estimées, mais incroyablement utiles du langage. Décortiquons ce concept, son fonctionnement interne dans la JVM, et pourquoi cette question cumule des milliers de vues sur Stack Overflow.
\n\nRéponse courte (pour ceux qui sont pressés)
\n\nUne classe imbriquée statique est une classe déclarée à l'intérieur d'une autre classe avec le mot-clé static. Contrairement à une classe interne (inner class), elle ne stocke pas de référence vers une instance de la classe externe. En substance, c'est une classe normale qui « vit » simplement à l'intérieur d'une autre classe pour un regroupement logique.
public class Externe {\n private static String secret = "Je suis un champ static";\n\n // Classe imbriquée statique\n public static class StatiqueInterne {\n public void afficherSecret() {\n // Peut accéder uniquement aux membres static de la classe externe\n System.out.println(secret);\n }\n }\n}\n\n// Utilisation\nExterne.StatiqueInterne objet = new Externe.StatiqueInterne();\nobjet.afficherSecret(); // Affiche : Je suis un champ static\n\nSimple ? Oui. Mais le diable se cache dans les détails. Allons plus loin.
\n\nComment cela fonctionne-t-il sous le capot de la JVM ?
\n\nLorsque le compilateur rencontre une classe imbriquée statique, il effectue deux opérations importantes :
\n\n- \n
- Crée un fichier .class séparé nommé
Externe$StatiqueInterne.class. Oui, le signe dollar n'est pas un hasard, c'est la convention standard de la JVM. \n - N'ajoute pas de référence cachée vers une instance de la classe externe. C'est la différence clé avec les classes internes non statiques. \n
Regardons « sous le capot » avec un décompilateur. Reprenons notre exemple ci-dessus et voyons ce qui se passe après compilation :
\n\n// Bytecode simplifié\npublic class Externe$StatiqueInterne {\n public void afficherSecret() {\n System.out.println(Externe.secret); // Accès direct au champ static\n }\n}\n\nRemarquez : il n'y a pas de this$0 (référence cachée vers la classe externe). Comparez maintenant avec une classe interne classique :
public class Externe {\n class InterneClassique {\n public void methode() {\n // Stocke implicitement une référence this$0 vers l'instance d'Externe\n }\n }\n}\n\nDans le bytecode d'une classe interne classique, le compilateur ajoute automatiquement un champ final Outer this$0. Cela signifie qu'une telle classe ne peut pas être créée sans une instance existante de la classe externe. La classe imbriquée statique, elle, est son propre maître.
Quand utiliser une classe imbriquée statique ? 3 scénarios concrets
\n\n1. Pattern Builder (Constructeur)
\n\nL'exemple le plus classique est le pattern Builder. Si vous avez déjà écrit new StringBuilder().append(...), vous avez utilisé les fruits des classes imbriquées statiques. Voici un exemple réel tiré de la bibliothèque standard Java :
public class Personne {\n private final String nom;\n private final int age;\n private final String email;\n\n private Personne(Builder builder) {\n this.nom = builder.nom;\n this.age = builder.age;\n this.email = builder.email;\n }\n\n // Classe imbriquée statique Builder\n public static class Builder {\n private String nom;\n private int age;\n private String email;\n\n public Builder setN