JEP 378 Blocs de Textes (Text Blocks)
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 :
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</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";
Histoire
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 6 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 permit 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 permit 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")
Mise en pratique
Les bases
Le délimiteur choisi fut trois caractères guillemet ( """ ). Concrêtement, ci-dessous, un exemple d’utilisation :
"""
line 1
line 2
line 3
"""
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 chariots 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.
"""
line 1
line 2
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"
Cas simples
Ci-dessous l’exemple du code HTML
String html = "<html>\n" +
" <body>\n" +
" <p>Hello, world</p>\n" +
" </body>\n" +
"</html>\n";
devient
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
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
String query = """
SELECT "EMP_ID", "LAST_NAME" FROM "EMPLOYEE_TB"
WHERE "CITY" = 'INDIANAPOLIS'
ORDER BY "EMP_ID", "LAST_NAME";
""";
Nous pouvons voir que cela permet clairement d’améliorer la lecture du code.
Espace blanc accidentel
Dans les exemples précédents, il est à noter que nous avons des espaces non significatifs au début de chaque ligne. Si nous matérialisons ces caractères avec le caractère point ( . ). Cela donne :
String html = """
..............<html>
.............. <body>
.............. <p>Hello, world</p>
.............. </body>
..............</html>
..............""";
En sachant que nous pouvons avoir aussi des caractères parasites en fin de lignes.
String html = """
..............<html>...
.............. <body>
.............. <p>Hello, world</p>....
.............. </body>.
..............</html>...
..............""";
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 :
|<html>|
| <body>|
| <p>Hello, world</p>|
| </body>|
|</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.
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
String html = """
<html>
<body>
<p>Hello, world</p>
</body>
</html>
""";
Nous allons de nouveau utiliser le caractère point ( . ) pour visualiser les espaces inutiles.
String html = """
........ <html>
........ <body>
........ <p>Hello, world</p>
........ </body>
........ </html>
........""";
Donc, nous obtenons le résultat suivant :
| <html>
| <body>
| <p>Hello, world</p>
| </body>
| </html>
Séquence d’échappements
Tous les séquences d’échappements définis 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
String code =
"""
String empty = "";
""";
ou
String code =
"""
String text = \"""
A text block inside a text block
\""";
""";
Nouvelles séquences d’échappements
A 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ère sur plusieurs lignes sans tenir compte du retour chariot.
String text = """
Lorem ipsum dolor sit amet, consectetur adipiscing \
elit, sed do eiusmod tempor incididunt ut labore \
et dolore magna aliqua.\
""";
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 significatifs, l’utilisation de cette séquence permet de le signaler.
Par exemple, dans l’exemple ci-dessous, les espaces en fin de ligne sont significatif car cela permet d’avoir des chaines de caractères de même longueur :
String colors = """
red \s
green\s
blue \s
""";
De nouveau, en utilisant le caractère pipe ( | ), cela permet de mieux visualiser le résultat.
|red |
|green|
|blue |
Références
Moteur de recherche
"Eduquer, ce n'est pas remplir des vases mais c'est d'allumer des feux." - Michel Montaigne
Billets récents
- Eclipse plante systématiquement sous Debian (et autres distribution Linux)
- JEP 463, Implicitly Declared Classes and Instance Main Methods (Second Preview)
- Debian - Montée de version de Debian 11 (Bullseye) à Debian 12 (Bookworm)
- JEP 451, Prepare to Disallow the Dynamic Loading of Agents
- JEP 444, Virtual Threads