Deux grosses nouveautés pour les développeurs sont apparues sur Java 13, les blocs de texte ainsi que l’apparition du mot clé « yield » sur les expressions switch.

Ensuite plusieurs nouveautés moins visibles pour les développeurs ayant un impact sur la mémoire et les performances ont été ajoutées, en l’occurrence la nouvelle implémentation de l’API Socket, une amélioration de la ZGC et enfin sur l’archivage dynamique des classes.

En ce qui concerne les blocs de textes ainsi que le mot clé « yield », il s’agit ici d’évolutions visibles uniquement sur la preview de Java 13.

Ces évolutions sont présentes dans le JDK mais ne sont pas activées par défaut. Il faut les activer explicitement pour pouvoir les utiliser. Il est préférable d’éviter de les utiliser en production car elles risquent d’être supprimées ou retirées dans les prochaines releases.

En ce qui concerne l’installation, tout d’abord il vous faut télécharger le JDK 13.

Une fois votre projet créé il vous faut sélectionner la version 13 du JDK, par exemple sur IntelliJ en cliquant sur File -> Project Structure, vous aurez alors l’interface présentée sur la capture ci-dessous, il faut sélectionner la version 13 pour « Project SDK » que vous venez de télécharger.

Pour que la compilation fonctionne avec les « Preview features » il faut sélectionner la version Preview dans le menu « Project language level ».

Preview Features

Il est également possible d’activer les « Preview Features » directement en ligne de commande, il faut alors compiler le code avec les paramètres suivants :

javac --enable-preview --release 13 VotreClasse.java

Et au moment de l’exécution :

java --enable-preview Example

Les blocs de texte (Text Blocks) dans Java 13

Comme beaucoup de nouvelles fonctionnalités (par exemple l’API Stream en Java 8), l’ajout de nouvelles fonctionnalités reste tardif sur Java. L’API Stream était présente sur d’autres langages avant la sortie de la version Java 8 qui introduisait ce concept, il est de même pour les blocs de texte, cette fonctionnalité existe déjà sur plusieurs autres langages ainsi que certains tournant également sur la JVM (notamment Kotlin et Groovy).

L’avantage principal de cette approche est que le langage n’intègre que des fonctionnalités ayant acquis une certaine maturité et les principales problématiques de ces fonctionnalités ont déjà été abordées sur les autres langages.

Les blocs de textes permettent d’écrire du texte sur plusieurs lignes sans avoir à utiliser le caractère « \n », mais également d’utiliser des caractères spéciaux sans avoir à les échapper avec le caractère « \ ».

Les blocs de textes sur plusieurs lignes en version java antérieure à 13 pouvaient alors s’écrire ainsi :

String sqlUsingPlus = "SELECT U.NAME FROM USER U \n" +
                      "INNER JOIN CITY C ON C.ID = U.CITY_ID \n" +
                      "WHERE CITY.NAME ? \n";

Ou encore en utilisant un StringJoiner qui va automatiquement ajouter à chaque fin de ligne le caractère de retour à la ligne « \n » :

StringJoiner sj = new StringJoiner(" \n");
sj.add("SELECT U.NAME FROM USER U");
sj.add("INNER JOIN CITY C ON C.ID = U.CITY_ID");
sj.add("WHERE CITY.NAME ? ");
sj.add("AND U.STATUS = ?");
String sql = sj.toString();

Voici l’écriture simplifiée en utilisant les blocs de textes de Java 13 :

String sqlWithTextBlock = """
SELECT U.NAME FROM USER U
INNER JOIN CITY C ON C.ID = U.CITY_ID
WHERE CITY.NAME ?""";

Il faut obligatoirement faire un retour à la ligne à la suite des «  » », le code suivant ne compilera pas :

// erreur de compilation
String notCompiling = """SELECT U.NAME FROM USER U
INNER JOIN CITY C ON C.ID = U.CITY_ID
WHERE CITY.NAME ?
AND U.STATUS = ?""";

L’indentation accidentelle à gauche n’est pas prise en compte, représentée ci-dessous dans le cadre rouge, elle correspond à l’indentation automatique lors du retour à la ligne.

Nous avons également trois nouvelles méthodes ajoutées sur la classe String qui sont associées aux blocs de texte.

1.La méthode String::formatted qui prend en paramètre une var-args (liste d’arguments variable) et qui va formater le bloc de texte avec les paramètres passés par exemple :

String sqlWithParameter = """
SELECT U.NAME FROM USER U
INNER JOIN CITY C ON C.ID = U.CITY_ID
WHERE CITY.NAME %s""".formatted("Paris");

2. La méthode String::stripIndent qui est utilisée notamment pour retirer l’indentation accidentelle évoquée plus tôt des blocs de texte, l’appel à la méthode sur la chaine de caractère suivante retirera l’indentation accidentelle représentée par les points :

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

3. La méthode String::translateEsapes qui elle retire les caractères d’échappement d’une chaine de caractère, la comparaison suivante est vraie :

String escapeTranslatedString = "\\n".translateEscapes();

escapeTranslatedString.equals("\n"); // true

Pour résumer ce qu’il faut retenir des blocs de texte :

  • Il faut commencer les blocs de texte par «  » » et un retour à la ligne et les terminer également avec «  » »
  • Toute l’indentation est conservée en dehors de l’indentation automatique (accidentelle de l’ide)
  • Il n’est plus nécessaire d’échapper les caractères spéciaux dans les blocs de texte

Évolution sur les expressions « switch » dans Java 13

C’est lors du développement de la JEP 305, qui contient une des grosses nouveautés de Java 14 le « pattern matching » (dont nous parlerons plus en détail dans un article sur Java 14), que plusieurs améliorations qui furent des prérequis ont été livrées en Java 13 sur les expressions switch.

De même que pour les « blocs de texte » les switch expressions restent également en preview. Le mot clé « yield » a été ajouté aux switch expressions, celui-ci remplace le break et permet de sortir de l’expression switch courante.

String errorLabel = switch (errorCode) {
    case 404:
        yield "Non trouvé!";
    case 418:
        yield "Je suis une théière!";
    case 500:
        yield "Erreur interne!";
    default:
        yield "Code inconnu!";
};

Attention le code suivant avec l’instruction break ne compilera alors plus :

String errorLabel = switch (errorCode) {
    case 404:
        break "Non trouvé!";// ne compile pas
    case 418:
        break "Je suis une théière!";// ne compile pas
    case 500:
        break "Erreur interne!";// ne compile pas
    default:
        break "Code inconnu!";"; // ne compile pas
};

Il est toujours possible d’utiliser l’opérateur arrow « -> » de la version 12, il est aussi possible de combiner yield avec l’opérateur arrow, ce qui permet par exemple sur l’instruction suivante d’ajouter une action et de retourner ensuite une valeur sur le bloc default du switch :

String errorLabel = switch (errorCode) {
    case 404 -> "Non trouvé!";
    case 418 -> "Je suis une théière!";
    case 500 -> "Erreur interne!";
    default -> {
        System.out.println("Erreur code inconnu");
        yield "Code inconnu!";
    }
};

Nouveautés moins visibles par les développeurs mais avec amélioration des performances et de la gestion de la mémoire par le JDK 

1.     Nouvelle implémentation de l’API Socket

Un coup de jeune a été donné pour l’API Socket qui date de plus de 20 ans, en effet l’implémentation existante basée sur un mix de code Java et C est compliquée à maintenir et à débuguer. Une nouvelle implémentation a alors été développée sur cette version 13.

L’implémentation par défaut avant Java 13 de la classe abstraite de la classe ServerSocket de la JDK ci-dessous était la classe PlainSocketImpl. Elle a été remplacée en Java 13 par l’implémentation NioSocketImpl (Nio pour Non-blocking Input/Output) :

public class ServerSocket implements java.io.Closeable {
  

    /**
     * The implementation of this Socket.
     */
    private SocketImpl impl;

Si cette implémentation pose problème il est également possible de repasser sur l’ancienne implémentation en modifiant la propriété jdk.net.usePlainSocketImpl au lancement de la JDK, par exemple pour lancer la classe Main :

 
java -Djdk.net.usePlainSocketImpl Main

2.     Les améliorations apportées à Z Garbage Collector (ZCG)

Le ZCG introduit en Java 11 a aussi été amélioré sur cette version 13, avant cette version celui-ci ne retournait pas la mémoire inutilisée au système d’exploitation. Ce comportement a été amélioré sur la version 13 ce qui permet d’optimiser l’empreinte mémoire notamment sur les conteneurs ou celle-ci est problématique.

3.     Archivage dynamique des classes

Nouveauté également de la version 13, décrite dans la JEP-350, l’archivage dynamique des classes (AppCDS), celui-ci offre des améliorations notables de performances et de mémoire par rapport à l’archivage classique (CDS).

Conclusion

Vous l’aurez compris la grosse nouveauté de cette version est l’intégration des blocs de texte dans le langage Java, initialement elle devait sortir sur la version précédente mais le développement n’était pas assez abouti.

Cette nouveauté se fait un peu tardivement par rapport aux autres langages mais aura acquis une certaine maturité grâce aux différentes implémentations existantes dont Java a pu s’en inspirer.

En espérant que cet article aura répondu à vos questions sur nouvelle itération et à bientôt pour un nouvel article sur cette fois-ci la version 14 !