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é qu'une conversion descendante peut échouer avec une ClassCastException si l'objet n'est pas réellement du type vers lequel vous effectuez la conversion. L'opérateur instanceof résout ce problème en vous permettant de vérifier le type d'un objet avant d'effectuer la conversion.
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(); // Sûr d'appeler les méthodes spécifiques à Dog
}Cette vérification empêche les erreurs d’exécution en garantissant que la conversion 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 la conversion en une seule étape à l’aide de l’appariement de motifs :
if (animal instanceof Dog dog) {
dog.bark(); // 'dog' est déjà casté et prêt à être utilisé
}Cette syntaxe plus claire élimine la ligne de conversion distincte. Notez que instanceof renvoie false lorsqu’il est testé avec null, vous n’avez donc pas besoin d’une vérification distincte de la valeur nulle.
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). Ajoutez un constructeur pour l’initialiser, une méthode gettergetModel(), ainsi qu’une méthodeinspect()qui affiche :Inspecting vehicle: [model]Car.java: Créez une classe qui étend Vehicle. Les voitures possèdent un champ supplémentairenumDoors(int). Utilisezsuperpour l’initialisation du parent. Ajoutez une méthodecheckDoors()qui affiche :[model] has [numDoors] doorsMotorcycle.java: Créez une autre classe qui étend Vehicle. Les motos possèdent un champhasSidecar(boolean). Ajoutez une méthodecheckSidecar()qui affiche soit[model] has a sidecar, soit[model] has no sidecarselon la valeur booléenne.Main.java: C’est ici queinstanceofdevient essentiel ! Vous recevrez quatre entrées : le modèle d’une voiture, le nombre de portes, le modèle d’une moto et l’indication de la présence d’un side-car (true/false).Créez un tableau de références
Vehiclecontenant une Car et une Motorcycle. Parcourez ensuite 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 une conversion descendante sûre et appelezcheckDoors() - Utilisez
instanceofpour vérifier s’il s’agit d’une Motorcycle — si c’est le cas, effectuez une conversion descendante sûre 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 has sidecar (boolean).
Votre sortie doit afficher quatre lignes : pour chaque véhicule, vous verrez son message d’inspection suivi de la vérification spécifique à son type. L’opérateur instanceof garantit que vous appelez uniquement les méthodes de Car sur de véritables Car et les méthodes de Motorcycle sur de véritables Motorcycle, ce qui évite toute ClassCastException !
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 le Car et le Motorcycle
// TODO: Parcourir le tableau et pour chaque véhicule :
// 1. Appeler la méthode inspect()
// 2. Utiliser instanceof pour vérifier si c'est un Car, puis faire un downcast et appeler checkDoors()
// 3. Utiliser instanceof pour vérifier si c'est un Motorcycle, puis faire 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érateurEntraînez-vous par vous-même : Compilateur Java en ligne