Tutoriel pour apprendre à écrire des blocks de texte avec la JEP 378 (nouveauté Java 15)

Lilian BENOIT

Cet article présente la JDK Enhancement Proposal (JEP) 378 (Text Blocks) qui permet l'écriture des chaines de caractères sur plusieurs lignes.

Pour réagir au contenu de cet article, un espace de dialogue vous est proposé sur le forum Commentez .

- Titre : Tutoriel pour apprendre à écrire des blocks de texte avec la JEP 378 (nouveauté Java 15)

- Auteur : Lilian BENOIT

- Parution : 4 mars 2021

- Licence : Copyright ® 2020 Lilian BENOIT. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Contexte

- II. Histoire

- III. Mise en pratique

- III-A. Les bases

- III-B. Cas simples

- III-C. Espace blanc accidentel

- III-D. Emplacement de la fermeture est importante

- III-E. Séquences d'échappement

- III-F. Nouvelles séquences d'échappement

- IV. Remerciements et références

I - Contexte

L'objectif est double :

- simplifier l'écriture d'un programme java ayant des chaines de caractères sur plusieurs lignes ;

- améliorer la lecture pour les langages non Java.

Pour illustrer le propos, voici un exemple de code Java avec la définition d'une variable sur plusieurs lignes :

1. String html = "<html>\n" +

2. "    <body>\n" +

3. "        <p>Hello, world</p>\n" +

4. "    </body>\n" +

5. "</html>\n";

Voici un second exemple avec le langage SQL :

String query = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n"+
"WHERE \"CITY\" = 'INDIANAPOLIS'\n" +
"ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";

II - Histoire

Table 1. Chronologie

Date

JDK

Nom / JEP

Mars 2019

JDK 12

Raw Strings Literals (Preview) (JEP 326)

Sept. 2019

JDK 13

Text Blocks (Preview) (JEP 355)

Mars 2020

JDK 14

Text Blocks (Second Preview) (JEP 368)

Sept. 2020

JDK 15

Text Blocks (JEP 378)

Cette fonctionnalité illustre parfaitement l'intérêt du nouveau cycle de sortie du JDK (tous les six mois, en mars et en septembre) et les aperçus de fonctionnalités « Preview features » (JEP 12).

En effet, la première proposition était « Raw Strings Literals (Preview) » (JEP 326) ciblée initialement pour le JDK 12 (mars 2019). Cependant, suite aux différents retours, la fonctionnalité a été retirée avant la finalisation de ce JDK.

Un sondage a permis de déterminer qu'il est préférable d'utiliser trois caractères guillemet (« " ») comme délimiteur et de prendre en compte les caractères d'échappement (comme \n par exemple).

De ce fait, cette fonctionnalité a été revue dans une nouvelle JEP « Text Blocks » (JEP 355) dans le JDK 13 (Sept 2019), toujours en mode « Preview ».

Par la suite, dans le JDK 14, une seconde JEP « Second Preview » (JEP 368) a été définie afin de consolider la nouvelle approche et d'ajouter des nouvelles séquences d'échappement.

Enfin, les retours ont permis de savoir que la fonctionnalité était mature et qu'elle pouvait être permanente. C'est pourquoi la dernière JEP (JEP 378) a été incluse dans la version 15 du JDK sans changement (hormis le retrait du mode « Preview »).

III - Mise en pratique

III-A - Les bases

Le délimiteur choisi fut trois caractères guillemet (« " »). Concrètement, ci-dessous, un exemple d'utilisation :

1. """

2. line 1

3. line 2

4. line 3

5. """

Cela correspond à

"line 1\nline 2\nline 3\n"

ou son équivalent

"line 1\n" +
"line 2\n" +
"line 3\n"

Nous pouvons remarquer que les retours chariot sont pris en compte. De ce fait, le positionnement du caractère de fermeture n'est pas anodin. Par exemple, nous pouvons avoir le caractère de fermeture en fin de ligne, et non sur une nouvelle ligne.

1. """

2. line 1

3. line 2

4. line 3"""

Par conséquent, il n'y a pas le dernier retour chariot. Donc, cela devient l'équivalent de

"line 1\nline 2\nline 3"

III-B - Cas simples

Ci-dessous l'exemple du code HTML

1. String html = "<html>\n" +

2. "    <body>\n" +

3. "        <p>Hello, world</p>\n" +

4. "    </body>\n" +

5. "</html>\n";

devient

1. String html = """

2. <html>

3. <body>

4. <p>Hello, world</p>

5. </body>

6. </html>

7. """;

En reprenant l'exemple avec le langage SQL, nous avons :

String query = "SELECT \"EMP_ID\", \"LAST_NAME\" FROM \"EMPLOYEE_TB\"\n"+
"WHERE \"CITY\" = 'INDIANAPOLIS'\n" +
"ORDER BY \"EMP_ID\", \"LAST_NAME\";\n";

devient

1. String query = """

2. SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"

3. WHERE "CITY" = 'INDIANAPOLIS'

4. ORDER BY "EMP_ID", "LAST_NAME";

5. """;

Nous pouvons voir que cela permet clairement d'améliorer la lecture du code.

III-C - Espace blanc accidentel

Dans les exemples précédents, il est à noter que nous avons des espaces non significatives au début de chaque ligne. Si nous matérialisons ces caractères avec le caractère point (« . »), cela donne :

1. String html = """

2. ..............<html>

3. ..............    <body>

4. ..............        <p>Hello, world</p>

5. ..............    </body>

6. ..............</html>

7. ..............""";

En sachant que nous pouvons avoir aussi des caractères parasites en fin de ligne.

1. String html = """

2. ..............<html>...

3. ..............    <body>

4. ..............        <p>Hello, world</p>....

5. ..............    </body>.

6. ..............</html>...

7. ..............""";

L'équipe savait que cela allait amener de la duplication de code ou des librairies pour traiter ces espaces inutiles. Donc, ils ont préféré prendre en charge ce point en mettant en place un algorithme.

De ce fait, nous allons utiliser le caractère pipe (« | ») afin de mieux visualiser le résultat de ce traitement :

1. |<html>|

2. |    <body>|

3. |        <p>Hello, world</p>|

4. |    </body>|

5. |</html>|

L'algorithme de réindentation sera normatif dans la spécification du langage Java. Les développeurs y auront accès via la méthode String::stripIdent.

III-D - Emplacement de la fermeture est importante

L'emplacement du caractère d'ouverture n'a pas d'importance. En revanche, l'emplacement du caractère de fermeture est très important, notamment s'il se trouve sur une nouvelle ligne.

Ainsi dans l'exemple suivant, le caractère de fermeture est décalé vers la droite

1. String html = """

2. <html>

3. <body>

4. <p>Hello, world</p>

5. </body>

6. </html>

7. """;

Nous allons de nouveau utiliser le caractère point (« . ») pour visualiser les espaces inutiles.

1. String html = """

2. ........      <html>

3. ........          <body>

4. ........              <p>Hello, world</p>

5. ........          </body>

6. ........      </html>

7. ........""";

Donc, nous obtenons le résultat suivant :

1. |      <html>

2. |          <body>

3. |              <p>Hello, world</p>

4. |          </body>

5. |      </html>

III-E - Séquences d'échappement

Toutes les séquences d'échappement définies dans les spécifications du langage Java (section 3.10.6) sont supportées. Les plus courantes sont : \n \t \' \" et \\.

L'utilisation du caractère guillemet (« " ») seul ou double est aussi possible. Nous pouvons par exemple écrire le code suivant :

1. String code =

2. """

3. String empty = "";

4. """;

ou

1. String code =

2. """

3. String text = \"""

4. A text block inside a text block

5. \""";

6. """;

III-F - Nouvelles séquences d'échappement

À partir de la seconde « Preview » (JEP 368), une nouvelle séquence d'espacement a été introduite : \<line-terminator>.

Cela permet d'écrire une chaine de caractères sur plusieurs lignes sans tenir compte du retour chariot.

1. String text = """

2. Lorem ipsum dolor sit amet, consectetur adipiscing \

3. elit, sed do eiusmod tempor incididunt ut labore \

4. et dolore magna aliqua.\

5. """;

Cela est l'équivalent à :

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

L'autre séquence est \s. Elle permet de se prémunir de la suppression des espaces en fin de ligne. C'est-à-dire, si les espaces en fin de ligne sont significatives, l'utilisation de cette séquence permet de le signaler.

Par exemple, dans l'exemple ci-dessous, les espaces en fin de ligne sont significatives, car cela permet d'avoir des chaines de caractères de même longueur :

1. String colors = """

2. red  \s

3. green\s

4. blue \s

5. """;

De nouveau, en utilisant le caractère pipe (« | »), cela permet de mieux visualiser le résultat.

|red  |
|green|
|blue |

IV - Remerciements et références

Cet article a été publié avec l'aimable autorisation de Lilian Benoit. L'article original (JEP 378 Blocs de Textes (Text Blocks)) peut être vu sur le blog https://www.lilian-benoit.fr/.

Nous tenons à remercier Claude Leloup pour sa relecture attentive de cet article et Winjerome pour la mise au gabarit.

- JEP 378: Text Blocks

- JEP 368: Text Blocks (Second preview)

- JEP 355: Text Blocks (Preview)

- JEP 326: Raw Strings Literal (Preview)

- JEP 12: Preview features

- Java Language Specification (JLS) section 3.10.6