Classes internes Java expliquées : Conception, Syntaxe et Usages pratiques
En Java, tout comme les méthodes et variables, une classe peut avoir une autre classe comme membre. Une classe écrite à l'intérieur d'une autre est une classe imbriquée (nested class), et la classe conteneur est la classe externe (outer class).
Classes imbriquées (Nested Classes)
Syntaxe
class Externe {
class Interne {
}
}
Deux types :
- Classes imbriquées non-statiques (inner classes) : membres d'instance
- Classes imbriquées statiques : membres statiques
Classes internes (Inner Classes - Non-statiques)
Mécanisme de sécurité : une classe top-level ne peut pas être private, mais une classe interne le peut. Cela permet aussi d'accéder aux membres privés de la classe externe.
Trois types selon l'endroit de définition :
- Classe interne (membre)
- Classe interne locale à une méthode
- Classe interne anonyme
Classe interne membre
class Externe {
int num;
// classe interne privée
private class Interne {
public void afficher() {
System.out.println("Ceci est une classe interne");
}
}
// Accès via une méthode
void afficherInterne() {
Interne interne = new Interne();
interne.afficher();
}
}
public class MaClasse {
public static void main(String args[]) {
Externe externe = new Externe();
externe.afficherInterne();
}
}
Résultat : Ceci est une classe interne.
Accès aux membres privés de la classe externe
Une classe interne peut accéder aux membres privés de sa classe externe.
class Externe {
private int num = 175;
public class Interne {
public int getNum() {
System.out.println("Méthode getNum de la classe interne");
return num; // accès au privé de Externe
}
}
}
public class MaClasse2 {
public static void main(String args[]) {
Externe externe = new Externe();
Externe.Interne interne = externe.new Interne(); // syntaxe spéciale
System.out.println(interne.getNum());
}
}
Résultat : Méthode getNum de la classe interne: 175
Instanciation : Externe.Interne interne = externe.new Interne();
Classe interne locale à une méthode
Définie à l'intérieur d'une méthode, sa portée est limitée à cette méthode. Ne peut être instanciée que dans cette méthode.
public class Externe {
void maMethode() {
int num = 23;
class InterneLocale {
public void afficher() {
System.out.println("Classe interne locale " + num); // capture variable locale
}
}
InterneLocale interne = new InterneLocale();
interne.afficher();
}
public static void main(String args[]) {
new Externe().maMethode();
}
}
Résultat : Classe interne locale 23
Note : la variable locale num doit être final ou "effectively final" (non modifiée après initialisation).
Classe interne anonyme
Classe sans nom, déclarée et instanciée simultanément. Utilisée pour surcharger une méthode d'une classe ou implémenter une interface.
Syntaxe
InterfaceOuClasseAbstraite ref = new InterfaceOuClasseAbstraite() {
public void methode() {
// implémentation
}
};
Exemple : surcharge de méthode
abstract class AnonymeInterne {
public abstract void maMethode();
}
public class ClasseExterne {
public static void main(String args[]) {
AnonymeInterne interne = new AnonymeInterne() {
public void maMethode() {
System.out.println("Exemple de classe interne anonyme");
}
};
interne.maMethode();
}
}
Résultat : Exemple de classe interne anonyme
Classe interne anonyme comme argument
Utile quand une méthode attend un objet d'interface, classe abstraite ou concrète.
// Interface
interface Message {
String saluer();
}
public class MaClasse {
public void afficherMessage(Message m) {
System.out.println(m.saluer() + ", exemple anonyme en argument");
}
public static void main(String args[]) {
MaClasse obj = new MaClasse();
obj.afficherMessage(new Message() {
public String saluer() {
return "Bonjour";
}
});
}
}
Résultat : Bonjour, exemple anonyme en argument
Classe imbriquée statique (Static Nested Class)
Membre statique de la classe externe. Accessible sans instancier la classe externe. N'a pas accès aux membres d'instance de la classe externe.
Syntaxe
class MonExterne {
static class ImbriqueeStatique {
}
}
Exemple
public class Externe {
static class Imbriquee {
public void maMethode() {
System.out.println("Ceci est ma classe imbriquée");
}
}
public static void main(String args[]) {
Externe.Imbriquee imbriquee = new Externe.Imbriquee();
imbriquee.maMethode();
}
}
Résultat : Ceci est ma classe imbriquée
Résumé des différences
| Caractéristique | Classe interne | Classe statique imbriquée |
|---|---|---|
| Accès membres d'instance externes | Oui | Non |
| Peut être private/protected | Oui | Oui |
| Instanciation | externe.new Interne() | Externe.Imbriquee() |
| Contexte d'utilisation | Liée à une instance | Utilitaire, indépendante |
Java
- Comprendre le mot-clé final en Java : variables, méthodes et classes
- L'opérateur instanceof en Java : guide complet
- Maîtriser les classes imbriquées et internes en Java : types, exemples et bonnes pratiques
- Comprendre les classes imbriquées statiques en Java : utilisation, différences et exemples
- Maîtriser les classes internes anonymes en Java : définition, syntaxe et exemples pratiques
- Le pattern Singleton en Java expliqué : implémentation et utilisation sûre
- Maîtriser la réflexion Java : inspection des classes, méthodes et champs à l'exécution
- Maîtriser Java ObjectOutputStream : Sérialisation, méthodes et exemples pratiques
- Maîtriser les génériques Java : Construire du code réutilisable et type-safe