JEP 406 - Pattern Matching for switch (Preview)

Première version preview du pattern matching dans switch (Java 17)

Numéro JEP

406

Statut

Preview

Introduit dans

Java 17 (LTS)

En résumé

JEP 406 est la première version preview du pattern matching pour switch, introduite dans Java 17. Cette fonctionnalité a ensuite été améliorée à travers plusieurs previews (JEP 420, JEP 427) avant d'être finalisée dans la JEP 433 avec Java 21. Cette page documente la version initiale.

⚠️ Note importante : Cette JEP est en mode preview. Pour l'utiliser en Java 17, vous devez activer les fonctionnalités preview avec --enable-preview. Pour la version finale et stable, consultez la JEP 433 (Java 21).

Contexte historique

Avant Java 17, le switch était limité à des constantes. Voici l'évolution :

  • Avant Java 12 : switch classique avec break
  • Java 12-13 : switch expressions (JEP 361)
  • Java 14 : switch expressions deviennent standard
  • Java 16 : pattern matching pour instanceof (JEP 394)
  • Java 17 : JEP 406 (preview) - pattern matching pour switch
  • Java 18-20 : JEP 420 et 427 (previews améliorées)
  • Java 21 : JEP 433 (final) - version stable

Nouveautés de la JEP 406

1. Type patterns dans switch

// Avant Java 17 : if-else verbeux
static String formater(Object obj) {
    String resultat;
    if (obj instanceof Integer i) {
        resultat = String.format("int %d", i);
    } else if (obj instanceof Long l) {
        resultat = String.format("long %d", l);
    } else if (obj instanceof Double d) {
        resultat = String.format("double %g", d);
    } else if (obj instanceof String s) {
        resultat = String.format("String %s", s);
    } else {
        resultat = obj.toString();
    }
    return resultat;
}

// Avec JEP 406 (Java 17 preview) : switch expression concis
static String formater(Object obj) {
    return switch (obj) {
        case Integer i -> String.format("int %d", i);
        case Long l    -> String.format("long %d", l);
        case Double d  -> String.format("double %g", d);
        case String s  -> String.format("String %s", s);
        default        -> obj.toString();
    };
}

2. Guarded patterns (patterns gardés)

static String evaluerTexte(String s) {
    return switch (s) {
        case null                       -> "Texte nul";
        case String t when t.isEmpty()  -> "Texte vide";
        case String t when t.length() < 5  -> "Texte court : " + t;
        default                         -> "Texte : " + s;
    };
}

3. Null handling

// Avant : NullPointerException
// Avec JEP 406 : gestion explicite de null
static String decrire(Object obj) {
    return switch (obj) {
        case null      -> "null";
        case String s  -> "String: " + s;
        case Integer i -> "Integer: " + i;
        default        -> "Autre";
    };
}

Exemples d'utilisation

Exemple 1 : Traitement de formes géométriques

sealed interface Shape permits Circle, Rectangle {}
record Circle(double rayon) implements Shape {}
record Rectangle(double largeur, double hauteur) implements Shape {}

static double calculerAire(Shape shape) {
    return switch (shape) {
        case Circle c    -> Math.PI * c.rayon() * c.rayon();
        case Rectangle r -> r.largeur() * r.hauteur();
    };
}

Exemple 2 : Validation avec guards

static String categoriserAge(Integer age) {
    return switch (age) {
        case null                  -> "Âge non spécifié";
        case Integer a when a < 0  -> "Âge invalide";
        case Integer a when a < 18 -> "Mineur";
        case Integer a when a < 65 -> "Adulte";
        default                    -> "Senior";
    };
}

Exemple 3 : Traitement de résultats

sealed interface Result {}
record Success(String data) implements Result {}
record Error(String message) implements Result {}

static String traiter(Result result) {
    return switch (result) {
        case Success s -> "OK : " + s.data();
        case Error e   -> "Erreur : " + e.message();
    };
}

Limitations de la version preview (JEP 406)

Cette première version avait quelques limitations qui seront résolues dans les versions ultérieures :

  • Syntaxe des guarded patterns moins aboutie
  • Certains cas d'exhaustivité non détectés
  • Pas de deconstruction patterns (record patterns) encore
  • Comportement avec null encore en évolution

Activation de la fonctionnalité preview

Compilation

javac --enable-preview --release 17 MonFichier.java

Exécution

java --enable-preview MonFichier

Maven

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.11.0</version>
            <configuration>
                <release>17</release>
                <compilerArgs>
                    <arg>--enable-preview</arg>
                </compilerArgs>
            </configuration>
        </plugin>
    </plugins>
</build>

Gradle

tasks.withType(JavaCompile) {
    options.compilerArgs += ['--enable-preview']
}

tasks.withType(Test) {
    jvmArgs += ['--enable-preview']
}

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

Évolution vers Java 21

Si vous souhaitez utiliser le pattern matching pour switch en production, nous recommandons :

  1. Java 17 (LTS) : Utilisez cette JEP 406 en mode preview pour expérimenter, mais pas en production
  2. Java 21 (LTS) : Utilisez la JEP 433 qui est la version finale et stable, recommandée pour la production

Différences avec la version finale (JEP 433)

Aspect JEP 406 (Java 17 preview) JEP 433 (Java 21 final)
Statut Preview Final / Stable
Guarded patterns Syntaxe when basique Syntaxe when améliorée
Record patterns Non supportés Supportés (JEP 440)
Exhaustivité Détection basique Détection complète
Production ❌ Non recommandé ✅ Recommandé

Recommandations

Pour Java 17

  • ✅ Expérimenter avec --enable-preview
  • ✅ Tester dans des projets personnels
  • ❌ Éviter en production (fonctionnalité preview)
  • ✅ Se préparer pour Java 21

Pour Java 21+

  • ✅ Utiliser la JEP 433 (version stable)
  • ✅ Déployer en production
  • ✅ Profiter des record patterns
  • ✅ Bénéficier de l'exhaustivité complète

Ressources