1. Le problème du instanceof classique
Commençons par un peu de nostalgie. Avant Java 16, lorsqu’il fallait vérifier le type d’un objet puis l’utiliser comme tel, on écrivait un modèle verbeux avec instanceof et un transtypage explicite :
Object obj = ...; // un objet quelconque
if (obj instanceof String) {
String s = (String) obj;
System.out.println("Longueur de la chaîne : " + s.length());
}
Banal mais fréquent
Ce pattern apparaît très souvent — gestionnaires d’événements, travail avec des collections hétérogènes, logique métier avec héritage, etc.
Pourquoi c’est peu pratique
- Duplication de code — il faut indiquer deux fois le type : dans instanceof et dans le transtypage.
- Risque d’erreur — on peut facilement trastyper vers le mauvais type et obtenir une ClassCastException.
- Code « bruyant » — dégrade la lisibilité, surtout avec des vérifications multiples.
2. Pattern Matching pour instanceof : nouvelle syntaxe
Avec Java 16, on a ajouté le pattern matching pour instanceof. On vérifie le type et on déclare aussitôt une variable du bon type, accessible dans la branche if.
Nouvelle syntaxe
if (obj instanceof String s) {
// s est déjà une chaîne !
System.out.println("Longueur de la chaîne : " + s.length());
}
- Après le type dans instanceof, on écrit le nom de la nouvelle variable : String s.
- La variable n’est accessible qu’à l’intérieur du bloc où la condition est vraie.
- Plus besoin d’écrire le transtypage (String) — le compilateur s’en charge.
Où est la magie ? Le compilateur vérifie le type et, s’il convient, « déplie » la variable du type requis. Sinon, le bloc ne s’exécute pas.
À quoi cela ressemble en code réel
Object obj = "Bonjour, Java 16+ !";
if (obj instanceof String s) {
System.out.println("Majuscules : " + s.toUpperCase());
} else {
System.out.println("Ce n’est pas une chaîne !");
}
3. Sécurité et lisibilité : pourquoi c’est génial
On élimine l’erreur ClassCastException
Object obj = 123;
// String s = (String) obj; // Boum ! Exception.
Avec le pattern matching, la variable n’est créée qu’en cas de vérification de type réussie — il n’y a tout simplement pas de « mauvais » transtypage.
Le code devient plus court et plus clair
Deux lignes deviennent une. Moins de code « bruyant » — plus facile à lire et à maintenir.
Exemple : traitement de différents types
public static void printInfo(Object obj) {
if (obj instanceof String s) {
System.out.println("Chaîne de longueur " + s.length());
} else if (obj instanceof Integer i) {
System.out.println("Entier : " + (i + 1));
} else {
System.out.println("Type inconnu : " + obj);
}
}
4. Exemples d’utilisation et nuances
Vérification de plusieurs types
Object value = ...;
if (value instanceof String s) {
System.out.println("C’est une chaîne : " + s);
} else if (value instanceof Number n) {
System.out.println("C’est un nombre : " + n);
} else {
System.out.println("Autre chose : " + value);
}
Utilisation avec null
Si l’objet vaut null, instanceof renverra toujours false — pas de NPE, mais le bloc ne s’exécutera pas.
Object obj = null;
if (obj instanceof String s) {
// Ce bloc ne s’exécutera JAMAIS si obj == null
System.out.println("Chaîne : " + s);
} else {
System.out.println("obj est null ou n’est pas une chaîne");
}
Pattern matching avec héritage
class Animal {}
class Dog extends Animal {
void bark() { System.out.println("Ouaf !"); }
}
Animal a = new Dog();
if (a instanceof Dog d) {
d.bark(); // Nous pouvons appeler les méthodes de Dog sans transtypage !
}
Rappel : l’ordre des vérifications est important. Allez du plus spécifique au plus général, sinon les vérifications « étroites » peuvent ne pas s’appliquer.
Comparaison : ancienne et nouvelle approche
| Ancienne méthode | Nouvelle méthode (pattern matching) |
|---|---|
|
|
5. Limitations du pattern matching pour instanceof
- Portée de la variable. La variable issue du motif n’est visible que dans la branche où la vérification est vraie.
if (obj instanceof String s) {
System.out.println(s); // s est accessible
}
// System.out.println(s); // Erreur ! s n’est pas visible ici
- Impossible de déclarer plusieurs variables de types différents dans une même condition.
// Erreur de compilation :
if (obj instanceof String s || obj instanceof Integer i) {
// ...
}
- Requiert Java 16+. Sur des versions plus anciennes du JDK, la nouvelle syntaxe n’est pas prise en charge.
6. Exemples pratiques (sur la base d’une application simple)
Imaginons un simple Task Manager avec différents types de tâches.
Classes
class Task {
String title;
public Task(String title) { this.title = title; }
}
class BugTask extends Task {
int severity;
public BugTask(String title, int severity) {
super(title);
this.severity = severity;
}
}
class FeatureTask extends Task {
String feature;
public FeatureTask(String title, String feature) {
super(title);
this.feature = feature;
}
}
Traitement avec pattern matching
public static void processTask(Task t) {
if (t instanceof BugTask bug) {
System.out.println("Bug : " + bug.title + ", criticité : " + bug.severity);
} else if (t instanceof FeatureTask feature) {
System.out.println("Fonctionnalité : " + feature.title + ", module : " + feature.feature);
} else if (t instanceof Task task) {
System.out.println("Tâche normale : " + task.title);
}
}
7. Nuances utiles
Tableau : pattern matching pour instanceof — avantages et inconvénients
| Avantages | Inconvénients/limitations |
|---|---|
| Moins de code, meilleure lisibilité | Nécessite Java 16+ |
| Pas de risque de ClassCastException | La variable n’est visible qu’à l’intérieur du bloc if |
| Sécurité des types au niveau du compilateur | Ne fonctionne pas pour plusieurs types dans une même condition |
| Pratique pour gérer l’héritage | Peut ne pas être pris en charge dans d’anciennes IDE et builds |
| Convient à toutes les classes |
Schéma visuel : comment fonctionne le pattern matching pour instanceof
+---------------------------+
| Object obj |
+---------------------------+
|
v
if (obj instanceof Type t)
|
Oui Non
(true) (false)
| |
v v
t disponible t n’existe pas
(code) (pas d’accès)
8. Erreurs courantes lors de l’utilisation du pattern matching for instanceof
Erreur n° 1 : tentative d’utiliser la variable en dehors du bloc if. Vous avez déclaré la variable dans le motif, puis vous êtes sorti du bloc — la variable n’existe plus. Le compilateur proteste à juste titre : « Qui est s ? »
Erreur n° 2 : croire que instanceof fonctionnera avec null. Si l’objet vaut null, la condition instanceof est toujours fausse, la variable n’est pas créée. Gérez null séparément si nécessaire.
Erreur n° 3 : utiliser la nouvelle syntaxe avec une ancienne version du JDK/IDE. Sous Java 11 et inférieur, le pattern matching pour instanceof n’est pas disponible — vous obtiendrez une erreur de syntaxe. Vérifiez la version du JDK.
Erreur n° 4 : confusion sur la portée. La variable issue du motif n’est accessible que dans la branche où la vérification est vraie. En dehors — elle n’existe pas.
Erreur n° 5 : s’attendre à la prise en charge de plusieurs types simultanément. Impossible de déclarer deux variables de types différents dans une seule condition : if (obj instanceof String s || obj instanceof Integer i) — c’est impossible. Pour chaque type, sa propre vérification.
GO TO FULL VERSION