Les principales nouveautés de Java 14

Voilà déjà un peu plus de six mois que Java 13 est sorti avec notamment une nouvelle manière d’utiliser le switch que Java 14 pointe le bout de son nez avec une version release sortie le 17 mars dernier.
Depuis la version 9 de Java SE en Septembre 2017, une nouvelle version sort tous les six mois. Il est important de noter que ces versions ne sont pas toutes LTS. Seules les versions 8 et 11 le sont à ce jour.

Voici une liste non exhaustive des nouveautés apportées par le Java 14 :

Nous allons dans cet article faire une présentation de ces cinq features.

    - JEP est l'acronyme de JDK Enhancement Proposal, comprenez Proposition d’amélioration du JDK.


    - Les Preview sont des JEP qui sont en phase de test et seront intégrées dans Java si elles reçoivent un avis favorable de la communauté.

Par défaut, elles sont désactivées et il faut ajouter l’option --enable-preview pour les utiliser.
Vous pouvez consulter la liste complète des features sur le site officiel d’OpenJDK : https://openjdk.java.net/projects/jdk/14/

Un message d’erreur pour des NPE plus précis

Quel développeur Java n’a jamais rencontré une NullPointerException (NPE) ?
Elles peuvent être une véritable corvée à débugger lorsque la ligne de code impactée résulte de plusieurs autres paramètres qui peuvent être null également.

player.club().stade().name();

Si dans cet exemple, un NPE est lancé. Il est difficile de savoir quel élément est null : player, club() ou stade() ?

Il faut généralement utiliser un débogueur pour analyser quelle variable ou méthode est à l’origine du problème. C’est une opération qui peut être chronophage et, avouons-le, pas forcément amusante à faire pour le développeur.

Avant Java 14

Exception in thread "main" java.lang.NullPointerException
	at features.TestJava14.main(TestJava14.java:24)

Désormais, le message associé à un objet de type NullPointerException nous donne une réponse plus utile au débuggage :

Java 14

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "utils.Stade.name()" because the return value of "utils.Club.stade()" is null at features.TestJava14.main(TestJava14.java:24)

On remarque l’apparition de deux termes :

  • Cannot invoke : l’élément à appeler (variable, retour de méthode, ...)
  • because : l’élément qui provoque le NPE
    Par défaut, cette feature est désactivée, il faut ajouter l’option : -XX:+ShowCodeDetailsInExceptionMessages au compilateur java pour l’activer.

Records (preview)

Une feature remarquable de cette version de Java est le record.

public record Stade(String name, int capacity) {}

Un record a les caractéristiques suivantes :

  1. C’est une classe spécialisée (comme les enum)
  2. Tous ses paramètres sont private final. Par conséquent, les données ne sont pas modifiables. (1)
  3. Les getters sont initialisés par défaut.
  4. Elle ne peut pas contenir des attributs de classes.
  5. Elle peut être initialisée sans corps (exemple ci-dessus).
  6. Elle ne peut pas bénéficier de l’héritage d’une autre classe.
  7. Elle peut implémenter des interfaces.

(1) : Un record n’est pas immuable car même si ses paramètres sont private final, si un record contient un objet muable, les attributs de cet objet pourront être modifiés via des setters.
C’est l’adresse mémoire de l’objet qui est private final et non pas son contenu.

Voici un second exemple avec une méthode et un paramètre de classe muable :

public record Adresse(LignesAdresse lignes, String codePostal, String ville) {

    public String fullAdress() {       
        return lignes + ", " + codePostal + " " + ville;   
    }
}
public class LigneAdresse {
   private String ligne1;
   private String ligne2;
   private String ligne3;
  
   //getters & setters
}

Dans cet exemple, l’objet de type LignesAdresse peut être modifié via un accesseur : lignes.setLigne1("43 Avenue de la Grande Armée");
Un record n’est donc pas immuable s’il contient en paramètre un objet dont les attributs peuvent être modifiés.

Pattern Matching pour instanceof (preview)

Un cas que l’on rencontre souvent dans le développement Java est l’utilisation d’un objet dont le compilateur ne connaît pas le type.
Pour ce faire, il faut tester le type de l’objet avec instanceof, transtyper l’objet dans une nouvelle variable pour pouvoir ensuite l’utiliser.

Avant Java 14

if (obj instanceof String) {    
    String s = (String) obj; // use s
}

Java 14

if (obj instanceof String s) {    
    // use s
}

Avec l’utilisation du pattern matching, on simplifie l’écriture car le transtypage se fait automatiquement dans la condition.

Switch Expression (Standard)

C’est une feature qui est apparue avec Java 12 et qui a été mise à jour dans la version 13 de Java.
Elle était en preview pour ces versions. Elle est désormais intégrée par défaut à partir du Java 14.

Ancienne façon de faire (avant Java 12)

switch(month) {   
    case JANUARY:   
    case FEBRUARY:   
    case MARCH:       
        System.out.println("Winter");       
        break;   
    case APRIL:   
    case MAY:   
    case JUNE:   
    case JULY:       
        System.out.println("Spring");       
        break;   
    case AUGUST:   
    case SEPTEMBER:       
        System.out.println("Summer");       
        break;   
    case OCTOBER:   
    case NOVEMBER:   
    case DECEMBER:       
        System.out.println("Autumn");       
        break;   
    default:       
        System.out.println("Is this month a valid one ?");
        break;
}

Java 12
Introduction d’une nouvelle manière de formuler le switch avec l’expression case L -> qui permet d’avoir un ou plusieurs labels séparés par une virgule pour exécuter le code à droite de l’expression.

switch(month) {   
    case JANUARY, FEBRUARY, MARCH -> System.out.println("Winter");   
    case APRIL, MAY, JUNE, JULY -> System.out.println("Spring");   
    case AUGUST, SEPTEMBER -> System.out.println("Summer");   
    case OCTOBER, NOVEMBER, DECEMBER -> System.out.println("Autumn");
    default -> System.out.println("Is this month a valid one ?");
}

Utilisation du mot-clé yield

Le Java 13 a signé l’introduction d’un nouveau mot-clé yield qui permet de faire retourner une valeur par un switch et de l’affecter à une variable.
Il remplace l’extension du mot-clé break (Java 12) jugée trop confuse pour les utilisateurs (break revient à son utilisation originelle).

String s = switch(month) {
    case JANUARY, FEBRUARY, MARCH:
        yield "Winter";
    case APRIL, MAY, JUNE, JULY:
        yield "Spring";   
    case AUGUST, SEPTEMBER:
        yield "Summer";
    case OCTOBER, NOVEMBER, DECEMBER:
        yield "Autumn";
    default:
        yield "Is this month a valid one ?";};

Text Blocks (Second Preview)

Les blocs de texte sont des chaînes de caractères sur plusieurs lignes. Elles sont très utilisées lors des développements pour des requêtes SQL, un template HTML ou du XML par exemple.

Avant Java 14

String html = "<html>\n" +
        "    <body>\n" +
        "        <p>Hello, world</p>\n" +
        "    </body>\n" +
        "</html>\n";

Java 14

String html = """
              <html>
                  <body>
                      <p>Hello, world</p>
                  </body>
              </html>
              """;

Dorénavant, il n’est plus nécessaire d’ajouter le signe + pour concaténer les lignes ni d’ajouter la séquence d’échappement \n pour le saut de ligne.
C’est remplacé par l’usage du triple guillemet """.

Résultat
Les deux exemples précédents affichent le même résultat.

<html>
    <body>
        <p>Hello, world</p>
    </body>
</html>

Nouvelles séquences d’échappement

Si l’on ne veut pas de saut de ligne, il suffit d’ajouter à chaque fin de ligne la séquence d’échappement \.

String text = """
                Lorem ipsum dolor sit amet, consectetur adipiscing \
                elit, sed do eiusmod tempor incididunt ut labore \
                et dolore magna aliqua \
                """;

Résultat

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua

Une autre nouvelle séquence d’échappement est \s qui permet d’ajouter un espace simple (\u0020). Elle permet également de garder les espaces qu’il y aurait avant cette séquence.

String text2 = """
       Lorem ipsum dolor sit amet, consectetur adipiscing \s
       elit, sed do eiusmod tempor incididunt ut labore \s
       et dolore magna aliqua \s
       """;

Résultat

Lorem ipsum dolor sit amet, consectetur adipiscing..elit, sed do eiusmod tempor incididunt ut labore..et dolore magna aliqua

Conclusion

Nous avons pu voir que cette nouvelle version de Java apportait son lot de nouvelles fonctionnalités.
Vous n’allez certainement pas les utiliser de si tôt en entreprise car :

  • La prochaine version LTS prévue par Oracle est Java 17 prévue pour septembre 2021
  • Une majorité des projets Java aujourd’hui se font sur du Java 8
  • La version LTS en cours est Java 11

Néanmoins, il est important de se mettre à jour et de savoir ce qui se fait de nouveau dans le monde Java en tant que développeur Java.
Si vous voulez tester ces exemples, vous pouvez télécharger un des JDK :

Il faut également que votre IDE (IntelliJ IDEA, Eclipse ou Netbeans) soit à jour et supporte les nouvelles fonctionnalités de Java 14.