SlideShare une entreprise Scribd logo
1
Les chaînes de "u0061" à " " "
Z " " ",
de String à StringTemplate
@jmdoudoux
JMdoudouX
Paris, 6 juin 2024
Sciam
Hello World avec Java en 1996
Traditionnellement le premier bout de code simple
Que l’on écrit lors de l’utilisation d’un nouveau langage
2
Le but : afficher la chaîne de caractères « Hello World »
Mon premier « Hello World » avec Java 1.0.1 en 1996
Le code doit être compilé et exécuté
public class Hello {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
C:java>javac Hello.java
C:java>java Hello
Hello world
Sciam
Hello World avec Java en 2024
Un « Hello World » avec Java 22 en 2024
3
C’est une fonctionnalité en preview
void main() {
System.out.println("Hello world");
}
C:java>java -version
openjdk version "22" 2024-03-19
OpenJDK Runtime Environment (build 22+35-2369)
OpenJDK 64-Bit Server VM (build 22+35-2369, mixed mode, sharing)
C:java>java --enable-preview --source 22 Hello.java
Hello world
Sciam
Hello World avec Java en 2024
Mon dernier « Hello World » avec Java 23 en 2024
4
Les choses ont bien changé
C’est toujours une fonctionnalité en preview
void main() {
println("Hello world");
}
C:java>java -version
openjdk version "23-ea" 2024-09-17
OpenJDK Runtime Environment (build 23-ea+25-2094)
OpenJDK 64-Bit Server VM (build 23-ea+25-2094, mixed mode, sharing)
C:java>java --enable-preview --source 23 Hello.java
Hello world
Beaucoup de choses ont changé concernant les chaînes de caractères
Sciam 5
Jean-Michel Doudoux
https://www.jmdoudoux.fr
@jmdoudoux
Co-fondateur du
Auteur d’un didacticiel depuis 2001
Diffusé sous licence GNU FDL
• Développons en Java (4200 pages)
Directeur technique
chez
Sciam
Les chaînes de caractères
Java est historiquement orienté objet
6
Tout est objet, sauf les types primitifs
Y compris les tableaux et les chaînes de caractères
Sciam
La classe qui encapsule une chaîne
La classe String n’existe pas
7
Il y a un import java.lang.* implicite dans chaque fichier source
C’est la classe java.lang.String
Il y a un import java.lang.String implicite dans chacune des slides
C:java>jshell
| Welcome to JShell -- Version 22
| For an introduction type: /help intro
jshell> Class.forName("String");
| Exception java.lang.ClassNotFoundException: String
jshell> Class.forName("java.lang.String");
$2 ==> class java.lang.String
Sciam
Des particularités syntaxiques
8
Affection d’une valeur littérale
String message = "Hello";
La concaténation avec l’opérateur +
String message = "Hello" +" World";
Sciam
Les instances
Sciam
L’obtention d’une instance
Affection d’une valeur littérale
10
String message = "Hello";
Les valeurs littérales sont mises dans le pool de String
Le compilateur effectue la concaténation de valeurs littérales
Donc une seule chaîne littérale, mise dans le pool
String message = "Hello" +" World";
Lors de la concaténation avec au moins une variable
Une nouvelle instance est créée
String hello = "Hello";
String message = hello +" World";
Sciam
L’obtention d’une instance
Invocation d’une des surcharges du constructeur
11
String vide = new String();
String message = new String("Hello");
String()
String(byte[] bytes)
String(byte[] ascii, int hibyte) deprécié en Java 1.1
String(byte[] bytes, int offset, int length) depuis 1.1
String(byte[] ascii, int hibyte, int offset, int count) deprécié en Java 1.1
String(byte[] bytes, int offset, int length, String charsetName) depuis Java 1.1
String(byte[] bytes, int offset, int length, Charset charset) depuis Java 1.6
String(byte[] bytes, String charsetName) depuis 1.1
String(byte[] bytes, Charset charset) depuis 1.6
String(char[] value)
String(char[] value, int offset, int count)
String(int[] codePoints, int offset, int count) depuis Java 1.5
String(String original)
String(StringBuffer buffer)
String(StringBuilder builder) depuis 1.5
L’opérateur new créé systématiquement une nouvelle instance
Sciam
Le pool de String
Cache d’instances de String
12
Par défaut, seules les valeurs littérales sont dans le pool
Historiquement, le pool de String est dans la PermGen
La méthode String::intern
Vérifie si une instance de String est égale à une qui se trouve dans le pool
Si elle est présente, alors l'instance de String du pool est renvoyée
Sinon, l'instance est ajoutée au pool et la référence à cette instance est renvoyée
A partir de Java 7, le pool de String est dans le heap
Sciam
Les chaînes dupliquées et le GC
Les chaînes peuvent occuper beaucoup de mémoire selon les cas
13
Et réduire l’encombrement mémoire
Le GC peut supprimer tous ces tableaux d’octets sauf un
Et réaffecter toutes les références d’instances de chaînes au tableau d’octets restant
Les chaînes elles-mêmes ne sont pas réellement dédupliquées
Comme le nom l’indique, seuls leurs tableaux d’octets le sont
Ne concerne que les instances dans la old/tenured generation
Le GC peut détecter les chaînes contenant les mêmes octets
Un certain nombre peuvent être des chaînes dupliquées
Grâce à la déduplication des chaînes (StringDeduplication)
En Java 18 pour SerialGC, ParallelGC et ZGC
Introduit en premier en Java 8u20 pour G1 ( JEP 192 )
Sciam
Les chaînes dupliquées et le GC
La déduplication de chaîne est désactivée par défaut
Doit être explicitement activée via -XX:+UseStringDeduplication
14
Par défaut, les chaînes deviennent éligibles à la déduplication
Que si elles ont survécu à trois GC
Peut être modifié avec l’option -XX:StringDeduplicationAgeThreshold
Pour avoir des statistiques de déduplication de chaînes à la console
Utiliser l’option -XX:+PrintStringDeduplicationStatistics en Java 8
Ou -Xlog:stringdedup*=debug à partir de Java 9
Comme toujours il faut mesurer selon le contexte
Impact potentiel sur les temps de pause
L'hypothèse est qu'un taux de réussite de la déduplication suffisamment élevé
Puisse équilibrer la majeure partie ou la totalité de cet impact
Sciam
L’encapsulation des caractères
Historique la classe String encapsule les caractères dans un char[]
15
Un caractère est stocké sur 2 octets, encodé en UTF-16
A partir de Java 9 : Compact Strings ( JEP 254 )
La classe String encapsule les caractères dans un byte[]
Avec un octet précise le format : UTF-16 ou Latin1
Réécriture de l’implémentation de la classe String
Pour réduire l’empreinte mémoire des chaînes de caractères utilisant le Latin1
Car une part du heap est utilisée pour les chaînes dans les applications de gestion
Aucun impact sur les méthodes publiques de la classe String
Désactivation possible avec l’option -XX:-CompactStrings
Sciam
L’immutabilité
Sciam
La classe java.lang.String
Propose de nombreuses méthodes pour modifier une chaîne
17
Mais la classe String est immutable
Elles retournent toutes une instance de type String
Qui contient une copie de la chaîne modifiée
String message = "Hello";
message.toUpperCase();
System.out.println(message);
Hello
String message = "Hello";
message = message.toUpperCase();
System.out.println(message);
HELLO
Sciam
Une classe vraiment immutable ?
NON
18
En utilisant l’API Reflection
import java.lang.reflect.Field;
public class TestString {
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
String chaine = "Hello";
Field f = String.class.getDeclaredField("value");
f.setAccessible(true);
f.set(chaine, "Salut".toCharArray());
System.out.println(chaine); // Affiche Salut
}
}
Sciam
Une classe vraiment immutable ?
A partir de Java 9, il faut remplacer le char[] par byte[]
19
Et autoriser l’introspection sur le package java.lang
Obligatoire à partir du JDK 16
C:java>java TestString
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private final byte[] java.lang.String.value accessible: module java.base
does not "opens java.lang" to unnamed module @3fee733d
at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:387)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:363)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:311)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:180)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:174)
at TestString.main(TestString.java:15)
…
f.set(chaine, "Salut".getBytes());
…
C:java>java --add-opens=java.base/java.lang=ALL-UNNAMED TestString
Salut
Sciam
Une classe vraiment immutable ?
A partir de Java 18, réimplémentation de l’API Reflection
En utilisant invokedynamic et MethodHandles ( JEP 416 )
20
Mais toujours possible en autorisant l’introspection
C:java>java TestString
Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private final byte[] java.lang.String.value accessible: module java.base
does not "opens java.lang" to unnamed module @2c7b84de
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:180)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:174)
at TestString.main(TestString.java:10)
C:java>java --add-opens=java.base/java.lang=ALL-UNNAMED TestString
Salut
Ne faites pas ça !!!
Sciam
La concaténation
Sciam
La concaténation
La langage Java autorise l’opérateur + sur des instances de type String
Depuis Java 1.0
22
Ce qui peut créer un nombre important d’instances
public class ConcatString {
public static void main(String[] args) {
String chaine = "Prix : "+args[0]+" euros";
System.out.println(chaine);
}
}
L’immutabilité implique la création d’une instance à chaque concaténation
Le JDK propose des classes pour gérer un ensemble de caractères mutable
Depuis Java 1.0, StringBuffer, thread-safe
Depuis Java 5, StringBuilder
Sciam
A partir de Java 6 (2006)
Le compilateur génère du byte code qui utilise StringBuilder
Lors de l’utilisation du + pour la concaténation
23
C:java>javap -c ConcatString
Compiled from "ConcatString.java"
public class ConcatString extends java.lang.Object{
public ConcatString();
public static void main(java.lang.String[]);
Code:
0: new #2; //class java/lang/StringBuilder
3: dup
4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V
7: ldc #4; //String Prix :
9: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
12: aload_0
13: iconst_0
14: aaload
15: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: ldc #6; //String euros
20: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
23: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
26: astore_1
27: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream;
30: aload_1
31: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
34: return
}
public class ConcatString {
public static void main(String[] args) {
String chaine = "Prix : "+args[0]+" euros";
System.out.println(chaine);
}
}
Utiliser StringBuilder
dans une boucle
Impossible de donner une
taille au constructeur
Sciam
A partir de Java 9 (2017)
Indify String Concatenation ( JEP 280 )
24
Utilisation d’un CallSite InvokeDynamic
Utilisation au runtime d’une stratégie de concaténation optimisée
Directement au sein de la JVM
Plusieurs stratégies de concaténation de chaînes :
-Djava.lang.invoke.stringConcat=<nom_strategie>
Par défaut MH_INLINE_SIZED_EXACT utilise des MethodHandles
Le JDK fournit des Bootstrap method
Dans la classe StringConcatFactory : makeConcat*()
Sciam
A partir de Java 9 (2017)
25
C:java>javap -c ConcatString
Compiled from "ConcatString.java"
public class ConcatString {
public ConcatString();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: aload_0
1: iconst_0
2: aaload
3: invokedynamic #2, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String;
8: astore_1
9: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream;
12: aload_1
13: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
16: return
}
public class ConcatString {
public static void main(String[] args) {
String chaine = "Prix : "+args[0]+" euros";
System.out.println(chaine);
}
}
Des performances équivalentes ou meilleures
Permet des évolutions et optimisations au runtime
Sans modification dans le compilateur
Sciam
L’encoding
L’un des deux sujets qui met en PLS les devs
Sciam
L’encodage des caractères en Java
Java utilise UTF-16 pour encoder du texte Unicode
27
Unicode est une norme de représentation de caractères
UTF-16 est un moyen d'encoder les caractères Unicode
Il y a deux concepts importants en Unicode à connaître :
- code point : est une valeur entière unique qui identifie un caractère
- code unit : est une séquence de bits utilisée pour coder un caractère (code point)
Raison pour laquelle la taille du type char en Java est de 2 octets
Les code points Unicode sont logiquement divisés en 17 plans
Le premier plan, le Basic Multilingual Plane (BMP)
Contient les caractères "classiques" (de U+0000 à U+FFFF)
Sciam
L’encodage des caractères en Java
Les autres plans contiennent les caractères "supplémentaires"
(de U+10000 à U+10FFFF)
28
Ils sont encodés sur au moins deux code units
Caractère : A
Code Point Unicode : U+0041
Code Unit(s) UTF-16 : u0041
Pour coder un caractère (code point)
Un ou plusieurs code units peuvent donc être nécessaires
Exemple
Caractère : 𝔸
Code Point Unicode : U+1D538
Code Unit(s) UTF-16 : uD835uDD38
Sciam
L’encodage des caractères en Java
La méthode String::length renvoie la taille de la chaîne
29
Selon la Javadoc
La taille est égale au nombre de code units Unicode dans la chaîne
Dans ce cas, utiliser String::codePointCount
Évidemment cela a des conséquences sur les traitements
jshell> String str = "𝕒𝕓𝕔";
str ==> "???"
jshell> str.codePointCount(0, str.length())
$2 ==> 3
jshell> str.length()
$3 ==> 6
Sciam
L’encoding par défaut des I/O
Historiquement l’encoding par défaut des I/O est celui du système
30
Pour pallier cela, il faut utiliser des surcharges qui acceptent un CharSet
Jusqu’à Java 17, le jeu de caractères par défaut dépend du système
Lors de l’utilisation d’API, si le charset à utiliser n’est pas précisé
Alors le charset par défaut est utilisé et peut donc varier d’un système à l’autre
BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8);
List<String> liste = Files.readAllLines(path, StandardCharsets.UTF_8);
Stream<String> lignes = Files.lines(path, StandardCharsets.UTF_8);
String contenu = Files.readString(path, StandardCharsets.UTF_8);
Sciam
UTF-8 par défaut
A partir de Java 18 : utilisation du charset UTF-8 par défaut ( JEP 400 )
Par les API du JDK, à l’exception des I/O sur la sortie standard
Pour améliorer la portabilité des données entrantes et sortantes d’une JVM
31
La propriété système file.encoding avec la valeur COMPAT
Pour revenir au comportement historique
La méthode PrintStream::charset
Permet de connaître le charset utilisé notamment dans la console
Sciam
UTF-8 par défaut
Javac considère que les fichiers sont encodés avec le charset par défaut
Soit celui du système avant JDK 18, UTF-8 à partir du JDK 18
Utilisation possible de l’option -encoding
32
public class Encoding {
public static void main(String[] args) {
String chaine = "𝕒𝕓𝕔";
System.out.println(chaine.length());
}
}
C:java>javac -version
javac 11.0.19
C:java>javac Encoding.java
Encoding.java:5: error: unmappable character (0x9D) for encoding
windows-1252
String chaine = "?òÆ?òô?òö";
^
3 errors
C:java>javac -encoding UTF8 Encoding.java
C:java>
Exemple sous Windows avec JDK 11 (charset par défaut CP-1252)
Source encodée en UTF-8
Sciam
UTF-8 par défaut
Exemple sous Windows avec JDK 18 (charset par défaut UTF-8)
33
C:java>javac -version
javac 18.0.2.1
C:java>javac Encoding.java
C:java>
public class Encoding {
public static void main(String[] args) {
String chaine = "𝕒𝕓𝕔";
System.out.println(chaine.length());
}
}
Source toujours encodée en UTF-8
Sciam
Le formatage
Historiquement, le JDK propose des classes de formatage
Qui s’enrichissent au fur et à mesure des versions
Sciam
La classe ListFormat
Java 22 : pour formater ou analyser une liste de chaîne de caractères
D’une manière sensible aux paramètres régionaux (Locale)
35
Le type de mise en forme avec l’énumération ListFormat.Type
Qui détermine la ponctuation entre les chaînes et les mots de liaison, le cas échéant
Valeurs définies : STANDARD (par défaut), OR et UNIT
var elements = List.of("E1", "E2", "E3");
System.out.println(ListFormat.getInstance().format(elements));
System.out.println(ListFormat.getInstance(Locale.FRANCE, OR, FULL).format(elements));
System.out.println(ListFormat.getInstance(Locale.US, STANDARD, FULL).format(elements));
System.out.println(ListFormat.getInstance(Locale.US, STANDARD, SHORT).format(elements));
E1, E2 et E3
E1, E2 ou E3
E1, E2, and E3
E1, E2, & E3
Une instance est obtenue avec une fabrique à qui on peut passer :
Le style de mise en forme avec l’énumération ListFormat.Style
Qui adapte la façon dont les chaînes sont abrégées (ou non) selon le type
Valeurs définies : FULL (par défaut), SHORT et NARROW
Sciam
Les blocs de texte
Sciam
Text Blocks
37
Preview en Java 13 et 14, standard en Java 15
Exprimer une chaîne de caractères littérale multi-lignes
Simplement : basiquement sans séquence d’échappement
Améliore la lisibilité de code source formaté (XML, JSON, HTML, …)
Compatibilité avec les chaînes de caractères
Et un délimiteur de fin
3 double quotes qui se suivent : """
Peut contenir zéro ou plusieurs caractères
Même des retours chariot, des double quotes sans échappement
Entourés par un délimiteur de début
3 double quotes qui se suivent : """
Zéro ou plusieurs caractères d’espacement
Un retour chariot
String html = """
<HTML>
<BODY>
<H1>"Hello"</H1>
</BODY>
</HTML>""";
Sciam
Text Blocks
38
Un bloc de texte ne peut donc pas être sur une seule ligne
Un bloc de texte est utilisable partout
Où une chaîne de caractères littérale peut être attendue
Gestion de l’indentation accessoire/significative
String html = """
""";
String html = """""";
En déplaçant le contenu vers la droite
En déplaçant le délimiteur de fermeture vers la gauche sur une ligne dédiée
Attention ajoute une ligne blanche à la fin
Sciam
Text Blocks
39
Les valeurs littérales des blocs de texte
Sont compilées vers le type : java.lang.String
Traitement en 3 étapes à la compilation
Les retours chariots sont normalisés en LF (u000A)
pour garantir le support multi-plateforme
Suppression de l’indentation accessoire en début et en fin
Interprétation des séquences d’échappement dans le texte
Sciam
Text Blocks
40
Peut contenir des caractères d’échappement (rarement utile)
Dont s (pour indiquer un espace) et <retour_chariot> (supprime la fin de ligne)
Les triples quotes dans le texte doivent être échappées : """
jshell> String message = """
...> azerty
...> azerty
...> azerty s
...> azerty
...> azerty
...> """;
message ==> " azerty azerty azerty n azerty azerty"
Sciam
L’interpolation
Sciam
String Templates (Second Preview)
42
Courant de devoir créer des chaînes de caractères composées
À partir d'une combinaison de textes littéraux
Et de valeurs ou d'expressions
Historiquement plusieurs fonctionnalités, toutes avec inconvénients
String s = x + " + " + y + " = " + (x + y);
MessageFormat mf = new MessageFormat("{0} + {1} = {2}");
String s = mf.format(x, y, x + y);
String s = String.format("%2$d + %1$d = %3$d", x, y, x + y);
String t = "%2$d + %1$d = %3$d".formatted(x, y, x + y);
String s = new StringBuilder()
.append(x)
.append(" + ")
.append(y)
.append(" = ")
.append(x + y)
.toString();
De nombreux langages proposent l'interpolation de chaînes
Comme alternative à la concaténation de chaînes
Première preview en Java 21 via la JEP 430, seconde preview JDK 22
Sciam
Safe Harbor
43
Tout le contenu de cette section est vrai …
Il sera probablement (très) différent …
Dans le futur
Avec le JDK 22
Sciam
String Templates (Second Preview)
44
La plupart des langages supportent l’interpolation de chaînes
Mais le résultat peut parfois engendrer des soucis indirects
Exemple : SQL ou JSON injection
En combinant :
- Un texte littéral avec des expressions intégrées
- Et un processeur de templates
Pour produire des chaînes de caractères construites dynamiquement
Avec la clarté de l’interpolation et un résultat plus sûr
Le but : enrichir le langage Java avec des string templates
Qui complètent les chaînes littérales et les blocs de texte
Possibilité de créer une instance de type quelconque
Avec un processeur de templates personnalisés
Sciam
String Templates (Second Preview)
45
Nouveau type d'expression dans le langage : les templates expressions
Pour effectuer une interpolation de chaîne afin de créer une chaîne ou un objet
Syntaxiquement, ressemble à une chaîne littérale avec un préfixe :
String prenom = "Jean-Michel";
String message = STR."Bonjour {prenom}";
Une template expression est composée de trois éléments :
1) Un processeur de templates (STR)
2) Un caractère point (U+002E), celui utilisé dans les autres expressions
3) Un template ("Bonjour {prenom}")
qui contient au moins une expression intégrée ( {prenom} )
Le template peut utiliser plusieurs lignes de code source
En utilisant une syntaxe similaire à celle des blocs de texte
String prenom = "Jean-Michel";
String message = STR."""
Bonjour
{prenom}""";
Sciam
String Templates (Second Preview)
46
3 processeurs de templates dans le JDK
StringTemplace.STR : effectue une interpolation pour créer une chaîne
int x = 10, y = 20;
String s = STR."{x} + {y} = {x + y}";
FormatProcessor.FMT : effectue une interpolation pour créer une chaîne
Il interprète les spécificateurs de format à gauche des expressions intégrées
Les spécificateurs de format sont ceux définis dans java.util.Formatter
StringTemplate.RAW : produit un objet de type StringTemplate
import static java.util.StringTemplate.RAW;
…
String prenom = "Jean-Michel";
StringTemplate st = RAW."Bonjour {prenom}";
String message = STR.process(st);
import static java.util.FormatProcessor.FMT;
…
int x = 10, y = 20;
String message = FMT."%05d{a} + %05d{b} = %05d{a + b}";
Sciam
String Templates (Second Preview)
47
Possibilité de définir des processeurs de templates personnalisés
Pour générer des chaînes ou des objets qui peuvent être validés
Une instance de l'interface fonctionnelle StringTemplate.Processor
Implémenter l’unique méthode process()
Utilisation de la fabrique StringTemplate.Processor::of
Pour obtenir une instance
var JSON = StringTemplate.Processor.of((StringTemplate st) -> new JSONObject(st.interpolate()));
String nom = "Durant";
String prenom = "Pierre";
JSONObject doc = JSON."""
{
"nom": "{nom}",
"prenom": "{prenom}"
}""";
Sciam
String Templates (Third preview)
48
Dans la JEP sur les fonctionnalités en preview
Il est prévu qu’elle puisse évoluer (voire même être supprimée)
En fonction des feed backs issus des previews
C’est le cas avec les String Templates
Une annonce est publiée sur la mailing list
Par Brian Goetz le 9 mars 2024
https://mail.openjdk.org/pipermail/amber-spec-experts/2024-March/004010.html
La fonctionnalité va profondément changer
Il va falloir attendre les détails
dans la prochaine JEP dans le JDK 23 24
Donc rendez-vous au prochain JavaDays 2025
Sciam
Conclusion
Sciam
Conclusion
Cette présentation a été l'occasion de faire un tour
De l'utilisation et de la manipulation de chaînes de caractères en Java
50
Les applications manipulent beaucoup de chaînes de caractères
Notamment celle de gestion
La syntaxe et les API ont beaucoup évolué
Pour faciliter la vie des développeurs
C’est important de migrer de JDK pour en bénéficier
Après presque 30 ans d’existence, Java continue d’évoluer
Le compilateur et la JVM ont aussi amélioré les performances
Des traitements des chaînes de caractères
Mêmes les sujets « faciles » doivent être creusés
Qui a eu tout juste aux Quizz ?
Sciam
Merci pour votre attention
Sciam

Contenu connexe

PDF
Les nouveautés de Java 22 - Oracle Dev Day mai 2024.pdf
PDF
Devoxx France 2023 - Les nouveautés de Java 19 et 20
PDF
Les nouveautés de Java 22 - Lorraine JUG avril 2024.pdf
PPTX
DOCX
Améliorations dans Java depuis la version 5
PDF
JAVA Chapitre7
PDF
Javaday Paris 2022 - Java en 2022 : profiter de Java 17
PDF
Nouveautés Java 9-10-11
Les nouveautés de Java 22 - Oracle Dev Day mai 2024.pdf
Devoxx France 2023 - Les nouveautés de Java 19 et 20
Les nouveautés de Java 22 - Lorraine JUG avril 2024.pdf
Améliorations dans Java depuis la version 5
JAVA Chapitre7
Javaday Paris 2022 - Java en 2022 : profiter de Java 17
Nouveautés Java 9-10-11

Similaire à Les chaines de a à Z, de String à StringTemplate.pdf (20)

PDF
Les nouveautés de Java 21 - YaJUG 2024.pdf
PDF
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
PPTX
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
PPTX
Introspection reflection
PDF
Les nouveautés de Java 21 - Devoxx France 2024.pdf
PDF
En route vers Java 21 - Javaday Paris 2023
PDF
Marzouk une introduction à jdbc
PDF
Voxxdays luxembourg 2016 retours java 8
PDF
Les nouveautés de Java 21 - Devoxx MA 2023.pdf
PPTX
Java version 11 - les 9 nouveautes
PDF
Les nouveautés de Java 21 - Rencontres dev Toulon octobre 2023.pdf
PDF
Les nouveautés de Java 19, 20 et 21 - RivieraDev 2023
PDF
Les nouveautés de Java 21 - Lorraing JUG mars 2024.pdf
PDF
Programmation Java
PDF
Java 9 modulo les modules devoxx fr 2017
PDF
Reseau
PDF
programmation réseau en java
PDF
Introduction java
PPTX
Présentation Javascript à l'ESI (Alger)
Les nouveautés de Java 21 - YaJUG 2024.pdf
devoxx 2022 - 10 ans de Devoxx FR et de Java.pdf
Java - Support etudiant - Tronc Commun Deuxième année ISIMA - 2018
Introspection reflection
Les nouveautés de Java 21 - Devoxx France 2024.pdf
En route vers Java 21 - Javaday Paris 2023
Marzouk une introduction à jdbc
Voxxdays luxembourg 2016 retours java 8
Les nouveautés de Java 21 - Devoxx MA 2023.pdf
Java version 11 - les 9 nouveautes
Les nouveautés de Java 21 - Rencontres dev Toulon octobre 2023.pdf
Les nouveautés de Java 19, 20 et 21 - RivieraDev 2023
Les nouveautés de Java 21 - Lorraing JUG mars 2024.pdf
Programmation Java
Java 9 modulo les modules devoxx fr 2017
Reseau
programmation réseau en java
Introduction java
Présentation Javascript à l'ESI (Alger)
Publicité

Plus de Jean-Michel Doudoux (12)

PDF
Du JDK 21 au JDK 25 - Java Days Paris - 5 juin 2025
PDF
30 ans d'Hello World en Java avec les JDK 1.0 à 24 -Devoxx FR 2025
PDF
35 nuances d'Hello World avec les JDK 1.0 à 23 - Meetup dev Paris novembre 2024
PDF
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDK
PDF
Lyon JUG 2018 - Java le changement c'est maintenant
PDF
Nantes jug 2018 - Java le changement c'est maintenant
PDF
Voxxeddays lux 2018 apres java 8, java 9 et 10
PDF
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMX
PDF
Devoxx 2018 Après Java 8, Java 9 et 10
PDF
Apres java 8, java 9 et 10 - BreizhCamp 2018
PDF
Retours sur java 8 devoxx fr 2016
PDF
"Input/Ouput, 16 ans après" à Devoxx France 2012
Du JDK 21 au JDK 25 - Java Days Paris - 5 juin 2025
30 ans d'Hello World en Java avec les JDK 1.0 à 24 -Devoxx FR 2025
35 nuances d'Hello World avec les JDK 1.0 à 23 - Meetup dev Paris novembre 2024
Voxxeddays Lux 2022 - Profiling et monitoring avec le JDK
Lyon JUG 2018 - Java le changement c'est maintenant
Nantes jug 2018 - Java le changement c'est maintenant
Voxxeddays lux 2018 apres java 8, java 9 et 10
Anniversaire Paris JUG - Deja 10 ans - retour vers le futur avec JMX
Devoxx 2018 Après Java 8, Java 9 et 10
Apres java 8, java 9 et 10 - BreizhCamp 2018
Retours sur java 8 devoxx fr 2016
"Input/Ouput, 16 ans après" à Devoxx France 2012
Publicité

Les chaines de a à Z, de String à StringTemplate.pdf

  • 1. 1 Les chaînes de "u0061" à " " " Z " " ", de String à StringTemplate @jmdoudoux JMdoudouX Paris, 6 juin 2024
  • 2. Sciam Hello World avec Java en 1996 Traditionnellement le premier bout de code simple Que l’on écrit lors de l’utilisation d’un nouveau langage 2 Le but : afficher la chaîne de caractères « Hello World » Mon premier « Hello World » avec Java 1.0.1 en 1996 Le code doit être compilé et exécuté public class Hello { public static void main(String[] args) { System.out.println("Hello world"); } } C:java>javac Hello.java C:java>java Hello Hello world
  • 3. Sciam Hello World avec Java en 2024 Un « Hello World » avec Java 22 en 2024 3 C’est une fonctionnalité en preview void main() { System.out.println("Hello world"); } C:java>java -version openjdk version "22" 2024-03-19 OpenJDK Runtime Environment (build 22+35-2369) OpenJDK 64-Bit Server VM (build 22+35-2369, mixed mode, sharing) C:java>java --enable-preview --source 22 Hello.java Hello world
  • 4. Sciam Hello World avec Java en 2024 Mon dernier « Hello World » avec Java 23 en 2024 4 Les choses ont bien changé C’est toujours une fonctionnalité en preview void main() { println("Hello world"); } C:java>java -version openjdk version "23-ea" 2024-09-17 OpenJDK Runtime Environment (build 23-ea+25-2094) OpenJDK 64-Bit Server VM (build 23-ea+25-2094, mixed mode, sharing) C:java>java --enable-preview --source 23 Hello.java Hello world Beaucoup de choses ont changé concernant les chaînes de caractères
  • 5. Sciam 5 Jean-Michel Doudoux https://www.jmdoudoux.fr @jmdoudoux Co-fondateur du Auteur d’un didacticiel depuis 2001 Diffusé sous licence GNU FDL • Développons en Java (4200 pages) Directeur technique chez
  • 6. Sciam Les chaînes de caractères Java est historiquement orienté objet 6 Tout est objet, sauf les types primitifs Y compris les tableaux et les chaînes de caractères
  • 7. Sciam La classe qui encapsule une chaîne La classe String n’existe pas 7 Il y a un import java.lang.* implicite dans chaque fichier source C’est la classe java.lang.String Il y a un import java.lang.String implicite dans chacune des slides C:java>jshell | Welcome to JShell -- Version 22 | For an introduction type: /help intro jshell> Class.forName("String"); | Exception java.lang.ClassNotFoundException: String jshell> Class.forName("java.lang.String"); $2 ==> class java.lang.String
  • 8. Sciam Des particularités syntaxiques 8 Affection d’une valeur littérale String message = "Hello"; La concaténation avec l’opérateur + String message = "Hello" +" World";
  • 10. Sciam L’obtention d’une instance Affection d’une valeur littérale 10 String message = "Hello"; Les valeurs littérales sont mises dans le pool de String Le compilateur effectue la concaténation de valeurs littérales Donc une seule chaîne littérale, mise dans le pool String message = "Hello" +" World"; Lors de la concaténation avec au moins une variable Une nouvelle instance est créée String hello = "Hello"; String message = hello +" World";
  • 11. Sciam L’obtention d’une instance Invocation d’une des surcharges du constructeur 11 String vide = new String(); String message = new String("Hello"); String() String(byte[] bytes) String(byte[] ascii, int hibyte) deprécié en Java 1.1 String(byte[] bytes, int offset, int length) depuis 1.1 String(byte[] ascii, int hibyte, int offset, int count) deprécié en Java 1.1 String(byte[] bytes, int offset, int length, String charsetName) depuis Java 1.1 String(byte[] bytes, int offset, int length, Charset charset) depuis Java 1.6 String(byte[] bytes, String charsetName) depuis 1.1 String(byte[] bytes, Charset charset) depuis 1.6 String(char[] value) String(char[] value, int offset, int count) String(int[] codePoints, int offset, int count) depuis Java 1.5 String(String original) String(StringBuffer buffer) String(StringBuilder builder) depuis 1.5 L’opérateur new créé systématiquement une nouvelle instance
  • 12. Sciam Le pool de String Cache d’instances de String 12 Par défaut, seules les valeurs littérales sont dans le pool Historiquement, le pool de String est dans la PermGen La méthode String::intern Vérifie si une instance de String est égale à une qui se trouve dans le pool Si elle est présente, alors l'instance de String du pool est renvoyée Sinon, l'instance est ajoutée au pool et la référence à cette instance est renvoyée A partir de Java 7, le pool de String est dans le heap
  • 13. Sciam Les chaînes dupliquées et le GC Les chaînes peuvent occuper beaucoup de mémoire selon les cas 13 Et réduire l’encombrement mémoire Le GC peut supprimer tous ces tableaux d’octets sauf un Et réaffecter toutes les références d’instances de chaînes au tableau d’octets restant Les chaînes elles-mêmes ne sont pas réellement dédupliquées Comme le nom l’indique, seuls leurs tableaux d’octets le sont Ne concerne que les instances dans la old/tenured generation Le GC peut détecter les chaînes contenant les mêmes octets Un certain nombre peuvent être des chaînes dupliquées Grâce à la déduplication des chaînes (StringDeduplication) En Java 18 pour SerialGC, ParallelGC et ZGC Introduit en premier en Java 8u20 pour G1 ( JEP 192 )
  • 14. Sciam Les chaînes dupliquées et le GC La déduplication de chaîne est désactivée par défaut Doit être explicitement activée via -XX:+UseStringDeduplication 14 Par défaut, les chaînes deviennent éligibles à la déduplication Que si elles ont survécu à trois GC Peut être modifié avec l’option -XX:StringDeduplicationAgeThreshold Pour avoir des statistiques de déduplication de chaînes à la console Utiliser l’option -XX:+PrintStringDeduplicationStatistics en Java 8 Ou -Xlog:stringdedup*=debug à partir de Java 9 Comme toujours il faut mesurer selon le contexte Impact potentiel sur les temps de pause L'hypothèse est qu'un taux de réussite de la déduplication suffisamment élevé Puisse équilibrer la majeure partie ou la totalité de cet impact
  • 15. Sciam L’encapsulation des caractères Historique la classe String encapsule les caractères dans un char[] 15 Un caractère est stocké sur 2 octets, encodé en UTF-16 A partir de Java 9 : Compact Strings ( JEP 254 ) La classe String encapsule les caractères dans un byte[] Avec un octet précise le format : UTF-16 ou Latin1 Réécriture de l’implémentation de la classe String Pour réduire l’empreinte mémoire des chaînes de caractères utilisant le Latin1 Car une part du heap est utilisée pour les chaînes dans les applications de gestion Aucun impact sur les méthodes publiques de la classe String Désactivation possible avec l’option -XX:-CompactStrings
  • 17. Sciam La classe java.lang.String Propose de nombreuses méthodes pour modifier une chaîne 17 Mais la classe String est immutable Elles retournent toutes une instance de type String Qui contient une copie de la chaîne modifiée String message = "Hello"; message.toUpperCase(); System.out.println(message); Hello String message = "Hello"; message = message.toUpperCase(); System.out.println(message); HELLO
  • 18. Sciam Une classe vraiment immutable ? NON 18 En utilisant l’API Reflection import java.lang.reflect.Field; public class TestString { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { String chaine = "Hello"; Field f = String.class.getDeclaredField("value"); f.setAccessible(true); f.set(chaine, "Salut".toCharArray()); System.out.println(chaine); // Affiche Salut } }
  • 19. Sciam Une classe vraiment immutable ? A partir de Java 9, il faut remplacer le char[] par byte[] 19 Et autoriser l’introspection sur le package java.lang Obligatoire à partir du JDK 16 C:java>java TestString Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private final byte[] java.lang.String.value accessible: module java.base does not "opens java.lang" to unnamed module @3fee733d at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:387) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:363) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:311) at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:180) at java.base/java.lang.reflect.Field.setAccessible(Field.java:174) at TestString.main(TestString.java:15) … f.set(chaine, "Salut".getBytes()); … C:java>java --add-opens=java.base/java.lang=ALL-UNNAMED TestString Salut
  • 20. Sciam Une classe vraiment immutable ? A partir de Java 18, réimplémentation de l’API Reflection En utilisant invokedynamic et MethodHandles ( JEP 416 ) 20 Mais toujours possible en autorisant l’introspection C:java>java TestString Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private final byte[] java.lang.String.value accessible: module java.base does not "opens java.lang" to unnamed module @2c7b84de at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:354) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:297) at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:180) at java.base/java.lang.reflect.Field.setAccessible(Field.java:174) at TestString.main(TestString.java:10) C:java>java --add-opens=java.base/java.lang=ALL-UNNAMED TestString Salut Ne faites pas ça !!!
  • 22. Sciam La concaténation La langage Java autorise l’opérateur + sur des instances de type String Depuis Java 1.0 22 Ce qui peut créer un nombre important d’instances public class ConcatString { public static void main(String[] args) { String chaine = "Prix : "+args[0]+" euros"; System.out.println(chaine); } } L’immutabilité implique la création d’une instance à chaque concaténation Le JDK propose des classes pour gérer un ensemble de caractères mutable Depuis Java 1.0, StringBuffer, thread-safe Depuis Java 5, StringBuilder
  • 23. Sciam A partir de Java 6 (2006) Le compilateur génère du byte code qui utilise StringBuilder Lors de l’utilisation du + pour la concaténation 23 C:java>javap -c ConcatString Compiled from "ConcatString.java" public class ConcatString extends java.lang.Object{ public ConcatString(); public static void main(java.lang.String[]); Code: 0: new #2; //class java/lang/StringBuilder 3: dup 4: invokespecial #3; //Method java/lang/StringBuilder."<init>":()V 7: ldc #4; //String Prix : 9: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 12: aload_0 13: iconst_0 14: aaload 15: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 18: ldc #6; //String euros 20: invokevirtual #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 23: invokevirtual #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 26: astore_1 27: getstatic #8; //Field java/lang/System.out:Ljava/io/PrintStream; 30: aload_1 31: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 34: return } public class ConcatString { public static void main(String[] args) { String chaine = "Prix : "+args[0]+" euros"; System.out.println(chaine); } } Utiliser StringBuilder dans une boucle Impossible de donner une taille au constructeur
  • 24. Sciam A partir de Java 9 (2017) Indify String Concatenation ( JEP 280 ) 24 Utilisation d’un CallSite InvokeDynamic Utilisation au runtime d’une stratégie de concaténation optimisée Directement au sein de la JVM Plusieurs stratégies de concaténation de chaînes : -Djava.lang.invoke.stringConcat=<nom_strategie> Par défaut MH_INLINE_SIZED_EXACT utilise des MethodHandles Le JDK fournit des Bootstrap method Dans la classe StringConcatFactory : makeConcat*()
  • 25. Sciam A partir de Java 9 (2017) 25 C:java>javap -c ConcatString Compiled from "ConcatString.java" public class ConcatString { public ConcatString(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: aload_0 1: iconst_0 2: aaload 3: invokedynamic #2, 0 // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;)Ljava/lang/String; 8: astore_1 9: getstatic #3 // Field java/lang/System.out:Ljava/io/PrintStream; 12: aload_1 13: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 16: return } public class ConcatString { public static void main(String[] args) { String chaine = "Prix : "+args[0]+" euros"; System.out.println(chaine); } } Des performances équivalentes ou meilleures Permet des évolutions et optimisations au runtime Sans modification dans le compilateur
  • 26. Sciam L’encoding L’un des deux sujets qui met en PLS les devs
  • 27. Sciam L’encodage des caractères en Java Java utilise UTF-16 pour encoder du texte Unicode 27 Unicode est une norme de représentation de caractères UTF-16 est un moyen d'encoder les caractères Unicode Il y a deux concepts importants en Unicode à connaître : - code point : est une valeur entière unique qui identifie un caractère - code unit : est une séquence de bits utilisée pour coder un caractère (code point) Raison pour laquelle la taille du type char en Java est de 2 octets Les code points Unicode sont logiquement divisés en 17 plans Le premier plan, le Basic Multilingual Plane (BMP) Contient les caractères "classiques" (de U+0000 à U+FFFF)
  • 28. Sciam L’encodage des caractères en Java Les autres plans contiennent les caractères "supplémentaires" (de U+10000 à U+10FFFF) 28 Ils sont encodés sur au moins deux code units Caractère : A Code Point Unicode : U+0041 Code Unit(s) UTF-16 : u0041 Pour coder un caractère (code point) Un ou plusieurs code units peuvent donc être nécessaires Exemple Caractère : 𝔸 Code Point Unicode : U+1D538 Code Unit(s) UTF-16 : uD835uDD38
  • 29. Sciam L’encodage des caractères en Java La méthode String::length renvoie la taille de la chaîne 29 Selon la Javadoc La taille est égale au nombre de code units Unicode dans la chaîne Dans ce cas, utiliser String::codePointCount Évidemment cela a des conséquences sur les traitements jshell> String str = "𝕒𝕓𝕔"; str ==> "???" jshell> str.codePointCount(0, str.length()) $2 ==> 3 jshell> str.length() $3 ==> 6
  • 30. Sciam L’encoding par défaut des I/O Historiquement l’encoding par défaut des I/O est celui du système 30 Pour pallier cela, il faut utiliser des surcharges qui acceptent un CharSet Jusqu’à Java 17, le jeu de caractères par défaut dépend du système Lors de l’utilisation d’API, si le charset à utiliser n’est pas précisé Alors le charset par défaut est utilisé et peut donc varier d’un système à l’autre BufferedReader reader = Files.newBufferedReader(path, StandardCharsets.UTF_8); List<String> liste = Files.readAllLines(path, StandardCharsets.UTF_8); Stream<String> lignes = Files.lines(path, StandardCharsets.UTF_8); String contenu = Files.readString(path, StandardCharsets.UTF_8);
  • 31. Sciam UTF-8 par défaut A partir de Java 18 : utilisation du charset UTF-8 par défaut ( JEP 400 ) Par les API du JDK, à l’exception des I/O sur la sortie standard Pour améliorer la portabilité des données entrantes et sortantes d’une JVM 31 La propriété système file.encoding avec la valeur COMPAT Pour revenir au comportement historique La méthode PrintStream::charset Permet de connaître le charset utilisé notamment dans la console
  • 32. Sciam UTF-8 par défaut Javac considère que les fichiers sont encodés avec le charset par défaut Soit celui du système avant JDK 18, UTF-8 à partir du JDK 18 Utilisation possible de l’option -encoding 32 public class Encoding { public static void main(String[] args) { String chaine = "𝕒𝕓𝕔"; System.out.println(chaine.length()); } } C:java>javac -version javac 11.0.19 C:java>javac Encoding.java Encoding.java:5: error: unmappable character (0x9D) for encoding windows-1252 String chaine = "?òÆ?òô?òö"; ^ 3 errors C:java>javac -encoding UTF8 Encoding.java C:java> Exemple sous Windows avec JDK 11 (charset par défaut CP-1252) Source encodée en UTF-8
  • 33. Sciam UTF-8 par défaut Exemple sous Windows avec JDK 18 (charset par défaut UTF-8) 33 C:java>javac -version javac 18.0.2.1 C:java>javac Encoding.java C:java> public class Encoding { public static void main(String[] args) { String chaine = "𝕒𝕓𝕔"; System.out.println(chaine.length()); } } Source toujours encodée en UTF-8
  • 34. Sciam Le formatage Historiquement, le JDK propose des classes de formatage Qui s’enrichissent au fur et à mesure des versions
  • 35. Sciam La classe ListFormat Java 22 : pour formater ou analyser une liste de chaîne de caractères D’une manière sensible aux paramètres régionaux (Locale) 35 Le type de mise en forme avec l’énumération ListFormat.Type Qui détermine la ponctuation entre les chaînes et les mots de liaison, le cas échéant Valeurs définies : STANDARD (par défaut), OR et UNIT var elements = List.of("E1", "E2", "E3"); System.out.println(ListFormat.getInstance().format(elements)); System.out.println(ListFormat.getInstance(Locale.FRANCE, OR, FULL).format(elements)); System.out.println(ListFormat.getInstance(Locale.US, STANDARD, FULL).format(elements)); System.out.println(ListFormat.getInstance(Locale.US, STANDARD, SHORT).format(elements)); E1, E2 et E3 E1, E2 ou E3 E1, E2, and E3 E1, E2, & E3 Une instance est obtenue avec une fabrique à qui on peut passer : Le style de mise en forme avec l’énumération ListFormat.Style Qui adapte la façon dont les chaînes sont abrégées (ou non) selon le type Valeurs définies : FULL (par défaut), SHORT et NARROW
  • 37. Sciam Text Blocks 37 Preview en Java 13 et 14, standard en Java 15 Exprimer une chaîne de caractères littérale multi-lignes Simplement : basiquement sans séquence d’échappement Améliore la lisibilité de code source formaté (XML, JSON, HTML, …) Compatibilité avec les chaînes de caractères Et un délimiteur de fin 3 double quotes qui se suivent : """ Peut contenir zéro ou plusieurs caractères Même des retours chariot, des double quotes sans échappement Entourés par un délimiteur de début 3 double quotes qui se suivent : """ Zéro ou plusieurs caractères d’espacement Un retour chariot String html = """ <HTML> <BODY> <H1>"Hello"</H1> </BODY> </HTML>""";
  • 38. Sciam Text Blocks 38 Un bloc de texte ne peut donc pas être sur une seule ligne Un bloc de texte est utilisable partout Où une chaîne de caractères littérale peut être attendue Gestion de l’indentation accessoire/significative String html = """ """; String html = """"""; En déplaçant le contenu vers la droite En déplaçant le délimiteur de fermeture vers la gauche sur une ligne dédiée Attention ajoute une ligne blanche à la fin
  • 39. Sciam Text Blocks 39 Les valeurs littérales des blocs de texte Sont compilées vers le type : java.lang.String Traitement en 3 étapes à la compilation Les retours chariots sont normalisés en LF (u000A) pour garantir le support multi-plateforme Suppression de l’indentation accessoire en début et en fin Interprétation des séquences d’échappement dans le texte
  • 40. Sciam Text Blocks 40 Peut contenir des caractères d’échappement (rarement utile) Dont s (pour indiquer un espace) et <retour_chariot> (supprime la fin de ligne) Les triples quotes dans le texte doivent être échappées : """ jshell> String message = """ ...> azerty ...> azerty ...> azerty s ...> azerty ...> azerty ...> """; message ==> " azerty azerty azerty n azerty azerty"
  • 42. Sciam String Templates (Second Preview) 42 Courant de devoir créer des chaînes de caractères composées À partir d'une combinaison de textes littéraux Et de valeurs ou d'expressions Historiquement plusieurs fonctionnalités, toutes avec inconvénients String s = x + " + " + y + " = " + (x + y); MessageFormat mf = new MessageFormat("{0} + {1} = {2}"); String s = mf.format(x, y, x + y); String s = String.format("%2$d + %1$d = %3$d", x, y, x + y); String t = "%2$d + %1$d = %3$d".formatted(x, y, x + y); String s = new StringBuilder() .append(x) .append(" + ") .append(y) .append(" = ") .append(x + y) .toString(); De nombreux langages proposent l'interpolation de chaînes Comme alternative à la concaténation de chaînes Première preview en Java 21 via la JEP 430, seconde preview JDK 22
  • 43. Sciam Safe Harbor 43 Tout le contenu de cette section est vrai … Il sera probablement (très) différent … Dans le futur Avec le JDK 22
  • 44. Sciam String Templates (Second Preview) 44 La plupart des langages supportent l’interpolation de chaînes Mais le résultat peut parfois engendrer des soucis indirects Exemple : SQL ou JSON injection En combinant : - Un texte littéral avec des expressions intégrées - Et un processeur de templates Pour produire des chaînes de caractères construites dynamiquement Avec la clarté de l’interpolation et un résultat plus sûr Le but : enrichir le langage Java avec des string templates Qui complètent les chaînes littérales et les blocs de texte Possibilité de créer une instance de type quelconque Avec un processeur de templates personnalisés
  • 45. Sciam String Templates (Second Preview) 45 Nouveau type d'expression dans le langage : les templates expressions Pour effectuer une interpolation de chaîne afin de créer une chaîne ou un objet Syntaxiquement, ressemble à une chaîne littérale avec un préfixe : String prenom = "Jean-Michel"; String message = STR."Bonjour {prenom}"; Une template expression est composée de trois éléments : 1) Un processeur de templates (STR) 2) Un caractère point (U+002E), celui utilisé dans les autres expressions 3) Un template ("Bonjour {prenom}") qui contient au moins une expression intégrée ( {prenom} ) Le template peut utiliser plusieurs lignes de code source En utilisant une syntaxe similaire à celle des blocs de texte String prenom = "Jean-Michel"; String message = STR.""" Bonjour {prenom}""";
  • 46. Sciam String Templates (Second Preview) 46 3 processeurs de templates dans le JDK StringTemplace.STR : effectue une interpolation pour créer une chaîne int x = 10, y = 20; String s = STR."{x} + {y} = {x + y}"; FormatProcessor.FMT : effectue une interpolation pour créer une chaîne Il interprète les spécificateurs de format à gauche des expressions intégrées Les spécificateurs de format sont ceux définis dans java.util.Formatter StringTemplate.RAW : produit un objet de type StringTemplate import static java.util.StringTemplate.RAW; … String prenom = "Jean-Michel"; StringTemplate st = RAW."Bonjour {prenom}"; String message = STR.process(st); import static java.util.FormatProcessor.FMT; … int x = 10, y = 20; String message = FMT."%05d{a} + %05d{b} = %05d{a + b}";
  • 47. Sciam String Templates (Second Preview) 47 Possibilité de définir des processeurs de templates personnalisés Pour générer des chaînes ou des objets qui peuvent être validés Une instance de l'interface fonctionnelle StringTemplate.Processor Implémenter l’unique méthode process() Utilisation de la fabrique StringTemplate.Processor::of Pour obtenir une instance var JSON = StringTemplate.Processor.of((StringTemplate st) -> new JSONObject(st.interpolate())); String nom = "Durant"; String prenom = "Pierre"; JSONObject doc = JSON.""" { "nom": "{nom}", "prenom": "{prenom}" }""";
  • 48. Sciam String Templates (Third preview) 48 Dans la JEP sur les fonctionnalités en preview Il est prévu qu’elle puisse évoluer (voire même être supprimée) En fonction des feed backs issus des previews C’est le cas avec les String Templates Une annonce est publiée sur la mailing list Par Brian Goetz le 9 mars 2024 https://mail.openjdk.org/pipermail/amber-spec-experts/2024-March/004010.html La fonctionnalité va profondément changer Il va falloir attendre les détails dans la prochaine JEP dans le JDK 23 24 Donc rendez-vous au prochain JavaDays 2025
  • 50. Sciam Conclusion Cette présentation a été l'occasion de faire un tour De l'utilisation et de la manipulation de chaînes de caractères en Java 50 Les applications manipulent beaucoup de chaînes de caractères Notamment celle de gestion La syntaxe et les API ont beaucoup évolué Pour faciliter la vie des développeurs C’est important de migrer de JDK pour en bénéficier Après presque 30 ans d’existence, Java continue d’évoluer Le compilateur et la JVM ont aussi amélioré les performances Des traitements des chaînes de caractères Mêmes les sujets « faciles » doivent être creusés Qui a eu tout juste aux Quizz ?
  • 52. Sciam