L'opérateur instanceof
Fait partie de la section Programmation Orientée Objet du Journey Java de Coddy — leçon 31 sur 87.
La leçon précédente a montré que le transtypage descendant (downcasting) peut échouer avec une ClassCastException si l'objet n'est pas réellement du type vers lequel vous effectuez le transtypage. L'opérateur instanceof résout ce problème en vous permettant de vérifier le type d'un objet avant le transtypage.
La syntaxe est simple : object instanceof ClassName renvoie true si l'objet est une instance de cette classe (ou de l'une de ses sous-classes) :
Animal animal = new Dog();
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark(); // Appel sécurisé des méthodes spécifiques à Dog
}Cette vérification évite les erreurs d'exécution en garantissant que le transtypage réussira. L'opérateur renvoie également true pour les types parents dans la hiérarchie :
Dog dog = new Dog();
System.out.println(dog instanceof Dog); // true
System.out.println(dog instanceof Animal); // true
System.out.println(dog instanceof Object); // trueDepuis Java 16, vous pouvez combiner la vérification et le transtypage en une seule étape en utilisant le filtrage par motif (pattern matching) :
if (animal instanceof Dog dog) {
dog.bark(); // 'dog' est déjà transtypé et prêt à l'emploi
}Cette syntaxe plus concise élimine la ligne de transtypage (cast) séparée. Notez que instanceof retourne false lorsqu'il est testé par rapport à null, vous n'avez donc pas besoin d'une vérification de nullité séparée.
Défi
FacileConstruisons un système d'inspection de véhicules qui utilise l'opérateur instanceof pour identifier et gérer en toute sécurité différents types de véhicules. Vous allez créer une hiérarchie de véhicules et écrire du code qui vérifie le type réel de chaque véhicule avant d'accéder à ses fonctionnalités spécialisées.
Vous organiserez votre code sur quatre fichiers :
Vehicle.java: Créez la classe de base que tous les véhicules partagent. Chaque véhicule possède un champmodel(String). Incluez un constructeur pour l'initialiser, une méthode gettergetModel(), et une méthodeinspect()qui affiche :"Inspecting vehicle: " + modelCar.java: Créez une classe qui étend Vehicle. Les voitures ont un champ supplémentairenumDoors(int). Utilisezsuperpour l'initialisation du parent. Ajoutez une méthodecheckDoors()qui affiche :getModel() + " has " + numDoors + " doors"Motorcycle.java: Créez une autre classe qui étend Vehicle. Les motos ont un champhasSidecar(boolean). Ajoutez une méthodecheckSidecar()qui affiche soitgetModel() + " has a sidecar"soitgetModel() + " has no sidecar"selon la valeur booléenne.Main.java: C'est ici queinstanceofdevient essentiel ! Vous recevrez quatre entrées : un modèle de voiture, le nombre de portes, un modèle de moto, et si elle a un side-car (true/false).Créez un tableau de références
Vehiclecontenant une Car et une Motorcycle. Ensuite, parcourez le tableau et pour chaque véhicule :- Appelez la méthode de base
inspect() - Utilisez
instanceofpour vérifier s'il s'agit d'une Car - si c'est le cas, effectuez un downcast sécurisé et appelezcheckDoors() - Utilisez
instanceofpour vérifier s'il s'agit d'une Motorcycle - si c'est le cas, effectuez un downcast sécurisé et appelezcheckSidecar()
- Appelez la méthode de base
Vous recevrez quatre entrées : le modèle de la voiture (String), le nombre de portes (int), le modèle de la moto (String), et si elle a un side-car (boolean).
Votre sortie devrait afficher quatre lignes - pour chaque véhicule, vous verrez son message d'inspection suivi de son test spécifique au type. L'opérateur instanceof garantit que vous n'appelez les méthodes de Car que sur des objets Car réels et les méthodes de Motorcycle sur des objets Motorcycle réels, évitant ainsi toute ClassCastException !
Aide-mémoire
L'opérateur instanceof vérifie si un objet est une instance d'une classe spécifique avant d'effectuer un transtypage (casting) :
Animal animal = new Dog();
if (animal instanceof Dog) {
Dog dog = (Dog) animal;
dog.bark(); // Appel sécurisé des méthodes spécifiques à Dog
}L'opérateur renvoie true pour la classe de l'objet et toutes les classes parentes dans la hiérarchie :
Dog dog = new Dog();
System.out.println(dog instanceof Dog); // true
System.out.println(dog instanceof Animal); // true
System.out.println(dog instanceof Object); // trueDepuis Java 16, le filtrage par motif (pattern matching) combine la vérification et le transtypage en une seule étape :
if (animal instanceof Dog dog) {
dog.bark(); // 'dog' est déjà transtypé et prêt à l'emploi
}L'opérateur instanceof renvoie false lorsqu'il est testé par rapport à null, ce qui élimine le besoin de vérifications de nullité séparées.
Essayez vous-même
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// Lire les entrées
String carModel = scanner.nextLine();
int numDoors = Integer.parseInt(scanner.nextLine());
String motorcycleModel = scanner.nextLine();
boolean hasSidecar = Boolean.parseBoolean(scanner.nextLine());
// TODO: Créer un objet Car avec carModel et numDoors
// TODO: Créer un objet Motorcycle avec motorcycleModel et hasSidecar
// TODO: Créer un tableau de références Vehicle contenant la Car et la Motorcycle
// TODO: Parcourir le tableau et pour chaque véhicule :
// 1. Appeler la méthode inspect()
// 2. Utiliser instanceof pour vérifier s'il s'agit d'une Car, puis effectuer un downcast et appeler checkDoors()
// 3. Utiliser instanceof pour vérifier s'il s'agit d'une Motorcycle, puis effectuer un downcast et appeler checkSidecar()
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesIntroduction à la POOClasses vs ObjetsLe mot-clé thisMéthodesChamps (Attributs)Méthode constructeurSurcharge de constructeurRécapitulatif - Calculatrice simple4Héritage
Héritage de base (extends)Le mot-clé superRedéfinition de méthode (@Override)Chaînage de constructeursLa classe ObjectHéritage simple et multiniveauPourquoi pas d'héritage multiple de classesRécapitulatif - Hiérarchie des employés7Méthodes spéciales et classe Object
Méthode toString()equals() et hashCode()Méthode clone()compareTo() et ComparableInterface ComparatorRécapitulatif - Tri personnalisé2Modificateurs d'accès et Encapsulation
Aperçu des niveaux d'accèsMéthodes Getter et SetterMasquage d'informationsLe mot-clé finalRécapitulatif - Gestionnaire de compte bancaire5Polymorphisme
Bases de la surcharge de méthodesRedéfinition de méthodes (Run-Time)Upcasting et DowncastingL'opérateur instanceofClasses et méthodes abstraitesRécapitulatif - Calculateur de formes8Concepts avancés de la POO
Composition vs HéritageAgrégation vs CompositionClasses internes, imbriquées et anonymesEnums et méthodes d'EnumRecords (Java 16+)Classes scellées (Java 17+)11Patrons de conception, partie 1
Introduction aux patrons de conceptionPatron SingletonPatron FabriquePatron MonteurPatron ObservateurPatron Stratégie3Propriétés de classe et membres statiques
Variables d'instance vs variables statiquesMéthodes statiquesBlocs statiquesConstantes (static final)Récapitulatif - Compteur et utilitaire6Interfaces et Classes Abstraites
Introduction aux InterfacesImplémentation d'InterfacesImplémentation d'Interfaces MultiplesDefault et Static dans les InterfacesClasses Abstraites vs InterfacesInterfaces FonctionnellesRécapitulatif - Système de Paiement9La généricité
Introduction à la généricitéClasses génériquesMéthodes génériquesParamètres de type bornésWildcards (?, extends, super)Récapitulatif - Conteneur générique12Patrons de conception, partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Template MethodPatron ÉtatPatron CompositePatron Itérateur