Maîtriser les classes imbriquées et internes en Java : types, exemples et bonnes pratiques
Classes imbriquées et internes en Java
Découvrez comment les classes imbriquées de Java améliorent l'encapsulation, la lisibilité, et permettent de puissants motifs de classes internes.
En Java, vous pouvez déclarer une classe à l'intérieur d'une autre classe – c'est ce qu'on appelle une classe imbriquée. Par exemple :
class OuterClass { // ... class NestedClass { // ... } }
Il y a deux saveurs principales de classes imbriquées :
- Classe imbriquée non-statique (communément appelée classe interne)
- Classe imbriquée statique
Lecture recommandée :
- Modificateurs d'accès Java
- Mot-clé static Java
Classe imbriquée non-statique (Classe interne)
Une classe interne réside dans une classe externe et peut accéder librement aux membres de la classe externe, même privés. Comme elle est liée à une instance de la classe externe, vous devez d'abord instancier la classe externe.
Exemple 1 : Classe interne
class CPU { double price; // classe interne class Processor{ double cores; String manufacturer; double getCache(){ return 4.3; } } // classe interne protégée protected class RAM{ double memory; String manufacturer; double getClockSpeed(){ return 5.5; } } } public class Main { public static void main(String[] args) { CPU cpu = new CPU(); CPU.Processor processor = cpu.new Processor(); CPU.RAM ram = cpu.new RAM(); System.out.println("Processor Cache = " + processor.getCache()); System.out.println("Ram Clock speed = " + ram.getClockSpeed()); } }
Sortie :
Processor Cache = 4.3 Ram Clock speed = 5.5
Ici, Processor et RAM sont imbriquées dans CPU. La classe RAM est déclarée protected, démontrant que les classes internes peuvent utiliser n'importe quel modificateur d'accès Java.
Dans Main, nous instancions d'abord la classe externe CPU, puis créons des instances de classe interne via l'instance externe :
CPU.Processor processor = cpu.new Processor; CPU.RAM ram = cpu.new RAM();
Astuce : L'opérateur point (.) est utilisé pour lier une instance de classe interne à son instance externe.
Accès aux membres de la classe externe depuis une classe interne
Les classes internes peuvent référencer les membres de la classe externe via le mot-clé this préfixé par le nom de la classe externe, ex. Car.this.carType. Cette syntaxe est nécessaire quand la classe interne a son propre contexte this.
Exemple 2 : Interaction avec la classe externe
class Car { String carName; String carType; public Car(String name, String type) { this.carName = name; this.carType = type; } private String getCarName() { return this.carName; } // classe interne class Engine { String engineType; void setEngine() { if(Car.this.carType.equals("4WD")){ if(Car.this.getCarName().equals("Crysler")) { this.engineType = "Smaller"; } else { this.engineType = "Bigger"; } } else { this.engineType = "Bigger"; } } String getEngineType(){ return this.engineType; } } } public class Main { public static void main(String[] args) { Car car1 = new Car("Mazda", "8WD"); Car.Engine engine = car1.new Engine(); engine.setEngine(); System.out.println("Engine Type for 8WD= " + engine.getEngineType()); Car car2 = new Car("Crysler", "4WD"); Car.Engine c2engine = car2.new Engine(); c2engine.setEngine(); System.out.println("Engine Type for 4WD = " + c2engine.getEngineType()); } }
Sortie :
Engine Type for 8WD= Bigger Engine Type for 4WD = Smaller
Même si getCarName() est private, la classe interne peut l'invoquer car elle réside dans la même classe externe.
Classe imbriquée statique
Une classe imbriquée statique ne nécessite pas d'instance de la classe externe pour être créée. Par conséquent, elle ne peut pas accéder directement aux membres non-statiques de la classe externe. Elle est créée en utilisant le nom de la classe externe :
OuterClass.NestedClass obj = new OuterClass.NestedClass();
Exemple 3 : Classe imbriquée statique
class MotherBoard { static class USB{ int usb2 = 2; int usb3 = 1; int getTotalPorts(){ return usb2 + usb3; } } } public class Main { public static void main(String[] args) { MotherBoard.USB usb = new MotherBoard.USB(); System.out.println("Total Ports = " + usb.getTotalPorts()); } }
Sortie :
Total Ports = 3
Exemple 4 : Tentative d'accès aux membres externes dans une classe imbriquée statique
class MotherBoard { String model; public MotherBoard(String model) { this.model = model; } static class USB{ int usb2 = 2; int usb3 = 1; int getTotalPorts(){ if(MotherBoard.this.model.equals("MSI")) { return 4; } else { return usb2 + usb3; } } } } public class Main { public static void main(String[] args) { MotherBoard.USB usb = new MotherBoard.USB(); System.out.println("Total Ports = " + usb.getTotalPorts()); } }
L'exécution de ce code produit :
error: non-static variable this cannot be referenced from a static context
Cette erreur survient car la classe imbriquée statique ne peut pas référencer MotherBoard.this sans instance externe.
Points clés à retenir
- Les classes internes sont traitées comme des membres réguliers de la classe externe et peuvent être déclarées
private,protected, oupublic. - Elles peuvent accéder librement à tous les membres de la classe externe, même ceux marqués
private. - Les classes imbriquées statiques ne nécessitent pas d'instance externe et ne peuvent pas accéder directement aux membres non-statiques externes.
- L'utilisation de classes imbriquées favorise l'encapsulation et garde la logique liée ensemble.
- Les classes internes sont idéales pour les callbacks, listeners, ou objets helpers fortement couplés à la classe externe.
Java
- Comprendre les classes imbriquées C# : Définition, utilisation et héritage
- Variables et littéraux en Java : Guide complet
- Classes et objets en Java : Guide pratique
- Comprendre le mot-clé final en Java : variables, méthodes et classes
- Classes et méthodes abstraites en Java : guide complet
- 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