CodeGym /Cours /JAVA 25 SELF /Classes imbriquées statiques (static nested)

Classes imbriquées statiques (static nested)

JAVA 25 SELF
Niveau 16 , Leçon 1
Disponible

1. Classe imbriquée statique

Une classe imbriquée statique (static nested class) est une classe déclarée à l’intérieur d’une autre classe avec le modificateur static. En substance, c’est une classe ordinaire qui « vit » à l’intérieur d’une autre classe, mais qui n’est pas liée à son objet.

Si une classe interne est comme un petit frère qui tient toujours la main de l’aîné (l’objet de la classe externe), alors une classe imbriquée statique est un cousin qui ne vient qu’aux fêtes de famille et vit sa propre vie le reste du temps.

Différences clés :

  • Pas de référence implicite à l’objet de la classe externe — pas de OuterClass.this ni d’accès aux membres non statiques.
  • Peut contenir des membres statiques (contrairement à une classe interne ordinaire).
  • Se crée sans objet de la classe externe.

Syntaxe de déclaration

Déclarer une classe imbriquée statique est très simple : on utilise le mot-clé static à l’intérieur de la classe externe.

class Outer {
    static class Nested {
        void print() {
            System.out.println("Hello from Nested!");
        }
    }
}

Et c’est tout ! Pas de constructions syntaxiques tordues — juste static class.

Visualisation :

Outer (classe externe)
│
├── Nested (classe imbriquée statique)
│      └── print()

2. Création d’une instance d’une classe imbriquée statique

Le plus agréable : aucun objet de la classe externe n’est nécessaire !

Outer.Nested nested = new Outer.Nested();
nested.print(); // Hello from Nested!

Notez que nous utilisons le nom complet de la classe — Outer.Nested. C’est comme s’adresser à la classe imbriquée par le nom de famille : « Smith.Fils ».

Comparez avec une classe interne (inner) :

Outer outer = new Outer();
Outer.Inner inner = outer.new Inner(); // nécessite un objet outer

Pour une static nested class, l’objet Outer n’est tout simplement pas nécessaire !

3. Accès aux membres de la classe externe

Voici la différence principale avec une classe interne.

  • Une classe imbriquée statique n’a accès QU’aux membres statiques de la classe externe.
  • Il est impossible d’accéder aux champs et méthodes non statiques (même s’ils sont public).

Exemple :

class Outer {
    private static int staticValue = 10;
    private int instanceValue = 20;

    static class Nested {
        void show() {
            System.out.println("Static value: " + staticValue); // OK
            // System.out.println("Instance value: " + instanceValue); // Erreur !
        }
    }
}

Si vous essayez d’accéder au champ non statique instanceValue, le compilateur vous fera aussitôt la leçon.

Pourquoi ? Parce qu’une static nested class ne « sait » pas à quel objet Outer elle doit être liée — elle ne possède pas de référence à l’objet de la classe externe.

4. Quand utiliser des classes imbriquées statiques

Quand sont-elles appropriées ?

  • Quand la classe imbriquée est logiquement liée à la classe externe, mais n’a pas besoin d’accéder à l’objet de la classe externe.
  • Quand vous souhaitez encapsuler une structure auxiliaire : par exemple, un builder, un utilitaire, une énumération ou même un petit objet immuable.
  • Quand vous voulez réduire l’« encombrement » du package : la classe n’est nécessaire qu’à la classe externe, inutile de la sortir.

Scénarios typiques :

  • Patron Builder (surtout pour les objets immuables)
  • Implémentation de structures auxiliaires : par exemple, des classes Node internes dans des collections
  • Regroupement de constantes ou d’utilitaires

Règle simple de choix
Posez-vous la question : « Mon classe imbriquée a-t-elle besoin d’accéder à un objet concret de la classe externe ? »
NON → utilisez une static class (classe imbriquée statique)
OUI → utilisez une class ordinaire (interne)

5. Exemples d’utilisation

Exemple 1 : Builder pour une classe

Supposons que nous avons une classe Person, et que nous voulons implémenter pour elle le patron Builder :

public class Person {
    private final String name;
    private final int age;

    // Constructeur privé
    private Person(Builder builder) {
        this.name = builder.name;
        this.age = builder.age;
    }

    // Classe imbriquée statique Builder
    public static class Builder {
        private String name;
        private int age;

        public Builder setName(String name) {
            this.name = name;
            return this;
        }

        public Builder setAge(int age) {
            this.age = age;
            return this;
        }

        public Person build() {
            return new Person(this);
        }
    }

    public void printInfo() {
        System.out.println("Person: " + name + ", " + age);
    }
}

Utilisation :

Person person = new Person.Builder()
    .setName("John")
    .setAge(30)
    .build();

person.printInfo(); // Person: John, 30

Pourquoi Builder est-il une classe imbriquée statique ?
Parce qu’il ne dépend pas de l’objet Person, il aide seulement à le créer. Il est logiquement lié à Person, mais pas à une instance concrète.

Exemple 2 : Structure auxiliaire dans une collection

Imaginons une classe « boîte de nombres », où un Node interne statique est utilisé pour stocker les éléments :

public class IntBox {
    private Node head;

    // Classe statique imbriquée
    private static class Node {
        int value;
        Node next;

        Node(int value) {
            this.value = value;
        }
    }

    public void add(int value) {
        Node node = new Node(value);
        node.next = head;
        head = node;
    }

    public void printAll() {
        Node current = head;
        while (current != null) {
            System.out.println(current.value);
            current = current.next;
        }
    }
}

Utilisation :

IntBox box = new IntBox();
box.add(1);
box.add(2);
box.add(3);
box.printAll(); // 3 2 1

Pourquoi Node est-il static ?
Parce que chaque Node n’a pas besoin de connaître toute la boîte (IntBox) ; il stocke simplement des données et une référence vers le Node suivant.

Exemple 3 : Classe utilitaire à l’intérieur de la principale

public class MathUtils {
    // Classe imbriquée statique pour travailler avec les nombres complexes
    public static class Complex {
        private final double re;
        private final double im;

        public Complex(double re, double im) {
            this.re = re;
            this.im = im;
        }

        public Complex add(Complex other) {
            return new Complex(this.re + other.re, this.im + other.im);
        }

        @Override
        public String toString() {
            return re + " + " + im + "i";
        }
    }
}

Utilisation :

MathUtils.Complex a = new MathUtils.Complex(1, 2);
MathUtils.Complex b = new MathUtils.Complex(3, 4);
MathUtils.Complex sum = a.add(b);
System.out.println(sum); // 4.0 + 6.0i

6. Points utiles

Classe interne vs classe imbriquée statique

Classe interne (inner) Classe imbriquée statique (static nested)
Mot-clé aucun
static
Référence implicite à l’objet externe oui non
Accès aux membres non statiques de la classe externe oui non
Accès aux membres statiques de la classe externe oui oui
Peut contenir des membres statiques non (seulement des constantes) oui
Syntaxe de création
outer.new Inner()
new Outer.Nested()
Utilisation Quand l’accès à l’objet de la classe externe est nécessaire Quand l’accès à l’objet de la classe externe n’est pas nécessaire

Illustration

flowchart LR
    OuterClass -->|has| InnerClass
    OuterClass -.->|has| StaticNestedClass
    StaticNestedClass -.->|can access| staticMembers
    InnerClass -->|can access| instanceMembers
    InnerClass -->|can access| staticMembers

Particularités et limites

  • Une static nested class peut contenir des champs et méthodes ordinaires comme statiques.
  • Elle peut être déclarée avec n’importe quel modificateur d’accès (public, private, protected, package-private).
  • Elle peut implémenter des interfaces et hériter d’autres classes.
  • Elle peut être generic.
  • Elle est généralement utilisée pour encapsuler des classes utilitaires qui ne sont pas nécessaires en dehors de la classe externe.

Exemple de generic static nested class :

public class Box {
    public static class Holder<T> {
        private T value;
        public Holder(T value) { this.value = value; }
        public T get() { return value; }
    }
}

Quand il NE faut PAS utiliser une static nested class

  • Si la classe imbriquée a besoin d’accéder aux champs/méthodes non statiques de la classe externe — utilisez une classe interne ordinaire.
  • Si la classe est nécessaire en dehors de la classe externe — mettez-la dans un fichier séparé.
  • Si la classe est trop grande ou complexe — mieux vaut en faire une classe séparée.

7. Erreurs typiques et nuances

Erreur n°1 : Confusion entre classe interne et classe imbriquée statique.
Beaucoup de débutants essaient, dans une static nested class, d’accéder aux champs non statiques de la classe externe. Mais une static nested class n’a pas de référence à l’objet de la classe externe, c’est donc impossible. Si vous avez besoin d’accéder à l’état d’un objet concret — utilisez une classe interne ordinaire.

Erreur n°2 : Tentative de créer une static nested class via un objet de la classe externe.
Il est inutile d’écrire outer.new Inner(). Pour une static nested class, utilisez toujours new Outer.Nested().

Erreur n°3 : Utiliser une static nested class pour une logique nécessitant l’accès à l’instance de la classe externe.
Si la logique de la classe est étroitement liée à l’état de l’objet de la classe externe, la static nested class est un mauvais choix. Utilisez une classe interne ordinaire.

Erreur n°4 : Imbrication trop complexe.
N’abusez pas des classes imbriquées. Si la structure devient confuse, il vaut mieux extraire certaines classes.

1
Mission
JAVA 25 SELF, niveau 16, leçon 1
Bloqué
Boîte à outils du magicien : activation d'un sort 🔮
Boîte à outils du magicien : activation d'un sort 🔮
1
Mission
JAVA 25 SELF, niveau 16, leçon 1
Bloqué
Coffre-fort secret : niveau d'accès 🛡️
Coffre-fort secret : niveau d'accès 🛡️
1
Mission
JAVA 25 SELF, niveau 16, leçon 1
Bloqué
Gestion des valeurs : chaîne d'artefacts 💎
Gestion des valeurs : chaîne d'artefacts 💎
1
Mission
JAVA 25 SELF, niveau 16, leçon 1
Bloqué
Maison d'édition : création d'un nouveau livre 📚
Maison d'édition : création d'un nouveau livre 📚
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION