0Pricing
Java Academy · Leçon

Classes internes et accès à la classe externe

Utilisez des classes internes non statiques qui conservent une référence vers l’instance de la classe externe.

Classes internes et accès à la classe externe est une leçon Java Academy gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage Java Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Java Academy comprend 4 leçons au total.

Classes internes

Une classe interne non statique contient une référence implicite vers l'instance de la classe externe qui l'englobe. Elle peut accéder à tous les membres de la classe externe, y compris ceux qui sont privés.

Déclarer et utiliser une classe interne

Créez une instance de classe interne uniquement via une instance de la classe externe, avec outer.new InnerClass().

class BankAccount {
    private double balance;
    private String owner;

    BankAccount(String owner, double initial) {
        this.owner = owner; this.balance = initial;
    }

    class Transaction {
        void deposit(double amount) {
            balance += amount; // accesses outer field directly
            System.out.println(owner + " deposited " + amount);
        }
    }
}

BankAccount acct = new BankAccount("Alice", 500);
BankAccount.Transaction tx = acct.new Transaction();
tx.deposit(100); // Alice deposited 100.0

Accéder aux membres externes

Les classes internes peuvent accéder à tous les membres de la classe externe, même à ses champs et méthodes privés.

class Encryption {
    private final String secretKey = "s3cr3t"; // private!

    class Encryptor {
        String encrypt(String data) {
            // Inner class accesses private outer field
            return data + "|" + secretKey.hashCode();
        }
    }

    class Decryptor {
        String decrypt(String encrypted) {
            int idx = encrypted.lastIndexOf('|');
            return encrypted.substring(0, idx);
        }
    }
}

Masquage avec this

Lorsqu'une classe interne possède un champ portant le même nom que celui de la classe externe, utilisez OuterClass.this.field pour faire référence au champ externe.

class Outer {
    int value = 10;

    class Inner {
        int value = 20; // shadows outer.value

        void printBoth() {
            System.out.println("Inner value: " + value);         // 20
            System.out.println("Outer value: " + Outer.this.value); // 10
        }
    }
}

new Outer().new Inner().printBoth();
// Inner value: 20
// Outer value: 10

Schéma Iterator avec une classe interne

Cas d'utilisation classique : implémenter un itérateur sous la forme d'une classe interne qui accède aux données privées de la collection englobante.

class NumberRange implements Iterable<Integer> {
    private final int start;
    private final int end;

    NumberRange(int start, int end) {
        this.start = start; this.end = end;
    }

    @Override
    public java.util.Iterator<Integer> iterator() {
        return new RangeIterator(); // inner class instance
    }

    private class RangeIterator implements java.util.Iterator<Integer> {
        private int current = start; // accesses outer start

        public boolean hasNext() { return current <= end; }
        public Integer next()    { return current++; }
    }
}

for (int n : new NumberRange(1, 5)) System.out.print(n + " ");
// 1 2 3 4 5

Écouteurs d'événements sous forme de classes internes

La programmation GUI et la programmation événementielle utilisent couramment des classes internes pour implémenter des écouteurs d'événements ayant accès à l'état du composant d'interface qui les englobe.

// Swing-style example (conceptual)
class LoginPanel {
    private String username = "";

    class LoginButtonListener {
        void onButtonClicked() {
            if (username.isEmpty()) {
                System.out.println("Please enter username"); // accesses outer field
            } else {
                System.out.println("Logging in as: " + username);
            }
        }
    }

    void setUsername(String name) { this.username = name; }
}
LoginPanel panel = new LoginPanel();
panel.setUsername("alice");
panel.new LoginButtonListener().onButtonClicked();
// Logging in as: alice

Classe interne dans les collections

Certaines implémentations de collections utilisent des classes internes pour contenir des curseurs ou des vues reposant sur la collection englobante.

class SimpleStack<T> {
    private Object[] elements;
    private int size = 0;

    SimpleStack(int capacity) {
        elements = new Object[capacity];
    }

    void push(T item) {
        if (size >= elements.length) throw new StackOverflowError();
        elements[size++] = item;
    }

    T pop() {
        if (size == 0) throw new java.util.EmptyStackException();
        T item = (T) elements[--size];
        elements[size] = null;
        return item;
    }

    int size() { return size; }
}

Avertissement concernant les fuites mémoire

Les instances de classes internes contiennent une référence vers l'instance externe. Si la classe interne échappe à la classe externe (par exemple, si elle est stockée dans une collection à longue durée de vie), l'instance externe ne peut pas être récupérée par le ramasse-miettes.

// Memory leak: anonymous inner class (implicit outer ref) stored statically
class LeakExample {
    byte[] data = new byte[1024 * 1024]; // 1MB

    // BAD: this Runnable holds a reference to LeakExample.this
    Runnable leak = new Runnable() {
        public void run() { System.out.println(data.length); }
    };
}
// If 'leak' is stored somewhere, LeakExample (and its 1MB) is never GC'd

// FIX: use a static nested class or a lambda that captures only needed values
static Runnable noLeak(byte[] data) {
    return () -> System.out.println(data.length); // captures array, not outer
}

Comparaison : classe interne ou lambda

Les lambdas Java modernes remplacent souvent les classes internes anonymes pour les interfaces à méthode unique. Les lambdas sont plus concises, mais ne possèdent NOT leur propre this.

// Old way: anonymous inner class
Runnable r1 = new Runnable() {
    @Override
    public void run() {
        System.out.println("Running (inner class) — this is the Runnable");
    }
};

// Modern: lambda
Runnable r2 = () -> System.out.println("Running (lambda)");

r1.run();
r2.run();

// Lambda this = enclosing class (not the Runnable)
// Inner class this = the Runnable instance itself

Quand utiliser des classes internes

Utilisez des classes internes non statiques lorsque :

  • La classe doit accéder à l'état privé de l'instance englobante
  • Chaque instance interne est logiquement liée à une instance externe précise
  • Le schéma Iterator sert à encapsuler la logique de parcours

Pratique : Paginator

Un Paginator pratique dont la classe interne conserve l’état de la page et accède à la liste de données de la classe englobante.

import java.util.*;

class Paginator<T> {
    private final List<T> items;
    private final int pageSize;

    Paginator(List<T> items, int pageSize) {
        this.items = items; this.pageSize = pageSize;
    }

    class Page {
        private int pageIndex = 0;

        List<T> current() {
            int start = pageIndex * pageSize;
            int end = Math.min(start + pageSize, items.size()); // outer
            return start < items.size() ? items.subList(start, end) : List.of();
        }
        boolean hasNext() { return (pageIndex + 1) * pageSize < items.size(); }
        void next() { if (hasNext()) pageIndex++; }
    }
}
Paginator<String> p = new Paginator<>(List.of("a","b","c","d","e"), 2);
Paginator.Page page = p.new Page();
System.out.println(page.current()); // [a, b]
page.next();
System.out.println(page.current()); // [c, d]

Vérification rapide

Que conserve une classe interne (non statique) contrairement à une classe imbriquée statique ?

Récapitulatif : classes internes et accès à la classe englobante

Points essentiels :

  • Les classes internes non statiques conservent une référence implicite vers l’instance englobante
  • Créez des instances internes uniquement à partir d’une instance englobante : outer.new Inner()
  • Les classes internes peuvent accéder à tous les membres de la classe englobante, y compris ses champs privés
  • Utilisez Outer.this.field pour distinguer des champs masqués
  • Cas d’utilisation privilégiés : Iterator, écouteurs d’événements et structures de données internes
  • Risque : les instances de classes internes empêchent les instances englobantes d’être libérées par le ramasse-miettes

Questions Fréquemment Posées

La leçon « Classes internes et accès à la classe externe » est-elle gratuite ?

Oui — le texte complet de « Classes internes et accès à la classe externe » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours Java Academy, passe à CoddyKit PRO. Le cours Java Academy comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Classes internes et accès à la classe externe » ?

Utilisez des classes internes non statiques qui conservent une référence vers l’instance de la classe externe. Tu pratiques Java Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer Java Academy ?

Aucune expérience préalable n'est requise. Java Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.

Combien de temps prend la leçon « Classes internes et accès à la classe externe » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon Java Academy ?

Oui. Chaque leçon Java Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Classes imbriquées statiques
  2. Classes internes et accès à la classe externe
  3. Classes locales et anonymes
  4. Choisir la bonne stratégie d’imbrication
← Retour à Java Academy