9. Chaînes de caractères en Java
Table des matières
- 9.1 Chaînes & Text Blocks
- 9.2 Méthodes principales des chaînes
- 9.2.1 Indexation des chaînes
- 9.2.2 Méthode length
- 9.2.3 Règles de bornes : index de début vs index de fin
- 9.2.4 Méthodes utilisant uniquement l’index de début (inclusif)
- 9.2.5 Méthodes avec début inclusif / fin exclusive
- 9.2.6 Méthodes opérant sur toute la chaîne
- 9.2.7 Accès aux caractères
- 9.2.8 Recherche
- 9.2.9 Méthodes de remplacement
- 9.2.10 Découpage et jonction
- 9.2.11 Méthodes retournant des tableaux
- 9.2.12 Indentation
- 9.2.13 Exemples supplémentaires
9.1 Chaînes & Text Blocks
9.1.1 Chaînes
9.1.1.1 Initialiser des chaînes
En Java, une String est un objet de la classe java.lang.String, utilisé pour représenter une séquence de caractères.
Les chaînes sont immutables : une fois créées, leur contenu ne peut pas être modifié. Toute opération qui semble modifier une chaîne en crée en réalité une nouvelle.
Vous pouvez créer et initialiser des chaînes de plusieurs façons :
String s1 = "Hello"; // string literal
String s2 = new String("Hello"); // using constructor (not recommended)
String s3 = s1.toUpperCase(); // creates a new String ("HELLO")
Note
- Les littéraux de chaîne sont stockés dans le
pool de String, une zone mémoire spéciale utilisée pour éviter de créer des objets chaîne en double. - L’utilisation du mot-clé
newcrée toujours un nouvel objet en dehors du pool.
9.1.1.2 Le String Pool
Comme les objets String sont immuables et largement utilisés, ils pourraient facilement occuper une grande quantité de mémoire dans un programme Java.
Pour réduire la duplication, Java réutilise toutes les chaînes déclarées comme littéraux (voir l’exemple ci-dessus), en les stockant dans une zone dédiée de la JVM appelée String Pool ou Intern Pool.
Veuillez consulter le paragraphe : "6.4.3 String Pool and Equality" dans le chapitre : Instanciation des types pour une explication et des exemples plus détaillés.
9.1.1.3 Caractères spéciaux et séquences d’échappement
Les chaînes peuvent contenir des caractères d’échappement, qui permettent d’inclure des symboles spéciaux ou des caractères de contrôle (caractères ayant une signification spéciale en Java).
Une séquence d’échappement commence par un backslash \.
Note
Table des caractères spéciaux & séquences d’échappement dans les chaînes
| Escape | Signification | Exemple Java | Résultat |
|---|---|---|---|
\" |
guillemet double | "She said \"Hi\"" |
She said "Hi" |
\\ |
backslash | "C:\\Users\\Alex" |
C:\Users\Alex |
\n |
nouvelle ligne (LF) | "Hello\nWorld" |
Hello + line break + World |
\r |
retour chariot (CR) | "A\rB" |
CR before B |
\t |
tabulation | "Name\tAge" |
Name Age |
\' |
guillemet simple | "It\'s ok" |
It's ok |
\b |
retour arrière (backspace) | "AB\bC" |
AC (le B est supprimé visuellement) |
\uXXXX |
unité de code Unicode | "\u00A9" |
© |
9.1.1.4 Règles de concaténation des chaînes
Comme introduit dans le chapitre sur Opérateurs Java, le symbole + représente normalement l’addition arithmétique lorsqu’il est utilisé avec des opérandes numériques.
Cependant, lorsqu’il est appliqué aux String, le même opérateur effectue la concaténation de chaînes — il crée une nouvelle chaîne en joignant les opérandes.
Comme l’opérateur + peut apparaître dans des expressions où des nombres et des chaînes sont présents, Java applique un ensemble spécifique de règles pour déterminer si + signifie addition numérique ou concaténation de chaînes.
9.1.1.5 Règles de concaténation
- Si les deux opérandes sont numériques,
+effectue l’addition numérique. - Si au moins un opérande est une
String, l’opérateur+effectue la concaténation de chaînes. - L’évaluation se fait strictement de gauche à droite, car
+est associatif à gauche.
Cela signifie qu’une fois qu’une String apparaît sur le côté gauche de l’expression, toutes les opérations + suivantes deviennent des concaténations.
Tip
Comme l’évaluation se fait de gauche à droite, la position du premier opérande String détermine comment le reste de l’expression est évalué.
- Exemples
// *** Pure numeric addition
int a = 10 + 20; // 30
double b = 1.5 + 2.3; // 3.8
// *** String concatenation when at least one operand is a String
String s = "Hello" + " World"; // "Hello World"
String t = "Value: " + 10; // "Value: 10"
// *** Left-to-right evaluation affects the result
System.out.println(1 + 2 + " apples");
// 3 + " apples" → "3 apples"
System.out.println("apples: " + 1 + 2);
// "apples: 1" + 2 → "apples: 12"
// *** Adding parentheses changes the meaning
System.out.println("apples: " + (1 + 2));
// parentheses force numeric addition → "apples: 3"
// *** Mixed types with multiple operands
String result = 10 + 20 + "" + 30 + 40;
// (10 + 20) = 30
// 30 + "" = "30"
// "30" + 30 = "3030"
String out = "3030" + 40; // "303040"
System.out.println(1 + 2 + "3" + 4 + 5);
// Step 1: 1 + 2 = 3
// Step 2: 3 + "3" = "33"
String r = "33" + 4; // "334"
// Step 4: "334" + 5 = "3345"
// *** null is represented as a string when concatenated
System.out.println("AB" + null);
// ABnull
9.1.2 Text Blocks (depuis Java 15)
Un text block est un littéral de chaîne multi-ligne introduit pour simplifier l’écriture de grandes chaînes (comme du HTML, du JSON ou du code) sans avoir besoin de nombreuses séquences d’échappement.
Un text block commence et se termine par trois guillemets doubles (""").
Vous pouvez utiliser les text blocks partout où vous utiliseriez des chaînes.
String html = """
<html>
<body>
<p>Hello, world!</p>
</body>
</html>
""";
Note
- Les text blocks incluent automatiquement les retours à la ligne et l’indentation pour la lisibilité. Les newlines sont normalisés en
\n. - Les guillemets doubles à l’intérieur du bloc n’ont généralement pas besoin d’être échappés.
- Le compilateur interprète le contenu entre les triples guillemets d’ouverture et de fermeture comme la valeur de la chaîne.
9.1.2.1 Mise en forme : espaces essentiels vs incidentels
- Espaces essentiels : espaces et newlines qui font partie du contenu de chaîne voulu.
- Espaces incidentels : indentation dans le code source que vous ne considérez pas conceptuellement comme faisant partie du texte.
String text = """
Line 1
Line 2
Line 3
""";
Important
- Caractère le plus à gauche (baseline) : la position du premier caractère non-espace sur l’ensemble des lignes (ou les
"""de fermeture) définit la baseline d’indentation. Les espaces à gauche de cette baseline sont considérés comme incidentels et sont supprimés. - La ligne immédiatement après les
"""d’ouverture n’est pas incluse dans la sortie si elle est vide (mise en forme typique). - Le newline avant les
"""de fermeture est inclus dans le contenu.
Dans l’exemple ci-dessus, la chaîne résultante se termine par un newline après"Line 3": il y a 4 lignes au total.
Sortie avec numéros de ligne (montrant la ligne vide finale) :
1: Line 1
2: Line 2
3: Line 3
4:
Pour supprimer le newline final :
- Utilisez un backslash de continuation de ligne à la fin de la dernière ligne de contenu.
- Placez les triples guillemets de fermeture sur la même ligne que le dernier contenu.
String textNoTrail_1 = """
Line 1
Line 2
Line 3\
""";
// OR
String textNoTrail_2 = """
Line 1
Line 2
Line 3""";
9.1.2.2 Nombre de lignes, lignes vides et retours à la ligne
- Chaque retour à la ligne visible à l’intérieur du bloc devient
\n. - Les lignes vides à l’intérieur du bloc sont conservées.
String textNoTrail_0 = """
Line 1
Line 2 \n
Line 3
Line 4
""";
Sortie :
1: Line 1
2: Line 2
3:
4: Line 3
5:
6: Line 4
7:
9.1.2.3 Text Blocks et caractères d’échappement
Les séquences d’échappement fonctionnent toujours à l’intérieur des text blocks lorsque nécessaire (par exemple, pour les backslashes ou des caractères de contrôle explicites).
String json = """
{
"name": "Alice",
"path": "C:\\\\Users\\\\Alice"
}\
""";
Vous pouvez également formater un text block en utilisant des placeholders et formatted() :
String card = """
Name: %s
Age: %d
""".formatted("Alice", 30);
9.1.2.4 Erreurs courantes (avec corrections)
// ❌ Mismatched delimiters / missing closing triple quote
String bad = """
Hello
World"; // ERROR — not a closing text block
// ✅ Fix
String ok = """
Hello
World
""";
// ❌ Text blocks require a line break after the opening """
String invalid = """Hello"""; // ERROR
// ✅ Fix
String valid = """
Hello
""";
// ❌ Unescaped trailing backslash at end of a line inside the block
String wrong = """
C:\Users\Alex\ // ERROR — backslash escapes the newline
Documents
""";
// ✅ Fix: escape backslashes, or avoid backslash at end of line
String correct = """
C:\\Users\\Alex\\
Documents\
""";
9.2 Méthodes principales des chaînes
9.2.1 Indexation des chaînes
Les chaînes en Java utilisent une indexation à base zéro, ce qui signifie :
- Le premier caractère est à l’index
0 - Le dernier caractère est à l’index
length() - 1 -
Accéder à un index en dehors de cette plage provoque une
StringIndexOutOfBoundsException -
Exemple :
String s = "Java";
// Indexes: 0 1 2 3
// Chars: J a v a
char c = s.charAt(2); // 'v'
9.2.2 Méthode length()
length() renvoie le nombre de caractères dans la chaîne.
String s = "hello";
System.out.println(s.length()); // 5
Le dernier index valide est toujours length() - 1.
9.2.3 Règles de bornes : index de début vs index de fin
De nombreuses méthodes de String utilisent deux indices :
- Index de début — inclusif
- Index de fin — exclusif
Autrement dit, substring(start, end) inclut les caractères depuis l’index start jusqu’à (mais sans inclure) l’index end.
- L’index de début doit être
>= 0et<= length() - 1 - L’index de fin peut être égal à
length()(la “position virtuelle” après le dernier caractère). - L’index de fin ne doit pas dépasser
length(). -
L’index de début ne doit jamais être supérieur à l’index de fin.
-
Exemple :
String s = "abcdef";
s.substring(1, 4); // "bcd" (indexes 1,2,3)
Cette règle s’applique à la plupart des méthodes basées sur substring.
9.2.4 Méthodes utilisant uniquement l’index de début (inclusif)
| Méthode | Description | Paramètres | Règle d’index | Exemple |
|---|---|---|---|---|
| substring(int start) | Renvoie la sous-chaîne de start à la fin | start | start inclusif | "abcdef".substring(2) → "cdef" |
| indexOf(String) | Première occurrence | — | — | "Java".indexOf("a") → 1 |
| indexOf(String, start) | Commence la recherche à l’index | start | start inclusif | "banana".indexOf("a", 2) → 3 |
| lastIndexOf(String) | Dernière occurrence | — | — | "banana".lastIndexOf("a") → 5 |
| lastIndexOf(String, fromIndex) | Recherche à rebours depuis l’index | fromIndex | fromIndex inclusif | "banana".lastIndexOf("a", 3) → 3 |
9.2.5 Méthodes avec début inclusif / fin exclusive
Ces méthodes suivent le même comportement de découpage : start inclus, end exclus.
| Méthode | Description | Signature | Exemple |
|---|---|---|---|
| substring(start, end) | Extrait une partie de la chaîne | (int start, int end) | "abcdef".substring(1,4) → "bcd" |
| regionMatches | Compare des régions de sous-chaînes | (toffset, other, ooffset, len) | "Hello".regionMatches(1, "ell", 0, 3) → true |
| getBytes(int srcBegin, int srcEnd, byte[] dst, int dstBegin) | Copie des caractères dans un tableau de bytes | début inclusif, fin exclusive | Copie les caractères dans [srcBegin, srcEnd) |
| copyValueOf(char[] data, int offset, int count) | Crée une nouvelle chaîne | offset inclusif ; offset+count exclusif | Même règle que substring |
9.2.6 Méthodes opérant sur toute la chaîne
| Méthode | Description | Exemple |
|---|---|---|
| toUpperCase() | Version en majuscules | "java".toUpperCase() → "JAVA" |
| toLowerCase() | Version en minuscules | "JAVA".toLowerCase() → "java" |
| trim() | Supprime les espaces en début/fin | " hi ".trim() → "hi" |
| strip() | Trim compatible Unicode | " hi\u2003".strip() → "hi" |
| stripLeading() | Supprime les espaces initiaux | " hi".stripLeading() → "hi" |
| stripTrailing() | Supprime les espaces finaux | "hi ".stripTrailing() → "hi" |
| isBlank() | Vrai si vide ou uniquement des espaces | " ".isBlank() → true |
| isEmpty() | Vrai si length == 0 | "".isEmpty() → true |
9.2.7 Accès aux caractères
| Méthode | Description | Exemple |
|---|---|---|
| charAt(int index) | Renvoie le caractère à l’index | "Java".charAt(2) → 'v' |
| codePointAt(int index) | Renvoie le point de code Unicode | Utile pour les emojis ou les caractères au-delà du BMP |
9.2.8 Recherche
| Méthode | Description | Exemple |
|---|---|---|
| contains(CharSequence) | Test de sous-chaîne | "hello".contains("ell") → true |
| startsWith(String) | Préfixe | "abcdef".startsWith("abc") → true |
| startsWith(String, offset) | Préfixe à l’index | "abc".startsWith("b", 1) → true |
| endsWith(String) | Suffixe | "abcdef".endsWith("def") → true |
9.2.9 Méthodes de remplacement
| Méthode | Description | Exemple |
|---|---|---|
| replace(char old, char new) | Remplace des caractères | "banana".replace('a','o') → "bonono" |
| replace(CharSequence old, CharSequence new) | Remplace des sous-chaînes | "ababa".replace("aba","X") → "Xba" |
| replaceAll(String regex, String replacement) | Remplacement regex global | "a1a2".replaceAll("\d","") → "aa" |
| replaceFirst(String regex, String replacement) | Seulement la première correspondance regex | "a1a2".replaceFirst("\d","") → "aa2" |
9.2.10 Découpage et jonction
| Méthode | Description | Exemple |
|---|---|---|
| split(String regex) | Découpe par regex | "a,b,c".split(",") → ["a","b","c"] |
| split(String regex, int limit) | Découpe avec limite | limit < 0 conserve toutes les chaînes vides finales |
9.2.11 Méthodes retournant des tableaux
| Méthode | Description | Exemple |
|---|---|---|
| toCharArray() | Renvoie char[] | "abc".toCharArray() |
| getBytes() | Renvoie byte[] en utilisant l’encodage plateforme/par défaut | "á".getBytes() |
9.2.12 Indentation
| Méthode | Description | Exemple |
|---|---|---|
| indent(int numSpaces) | Ajoute (positif) ou supprime (négatif) des espaces au début de chaque ligne ; ajoute aussi un retour à la ligne final s’il n’est pas déjà présent | str.indent(-20) |
| stripIndent() | Supprime tous les espaces initiaux incidentels de chaque ligne ; n’ajoute pas de retour à la ligne final | str.stripIndent() |
- Exemple :
var txtBlock = """
a
b
c""";
var conc = " a\n" + " b\n" + " c";
System.out.println("length: " + txtBlock.length());
System.out.println(txtBlock);
System.out.println("");
String stripped1 = txtBlock.stripIndent();
System.out.println(stripped1);
System.out.println("length: " + stripped1.length());
System.out.println("*********************");
System.out.println("length: " + conc.length());
System.out.println(conc);
System.out.println("");
String stripped2 = conc.stripIndent();
System.out.println(stripped2);
System.out.println("length: " + stripped2.length());
Sortie :
length: 9
a
b
c
a
b
c
length: 9
*********************
length: 8
a
b
c
a
b
c
length: 5
9.2.13 Exemples supplémentaires
- Exemple 1 — Extraire
[start, end)
String s = "012345";
System.out.println(s.substring(2, 5));
// includes 2,3,4 → prints "234"
- Exemple 2 — Recherche à partir d’un index de début
String s = "hellohello";
int idx = s.indexOf("lo", 5); // search begins at index 5
- Exemple 3 — Pièges courants
String s = "abcd";
System.out.println(s.substring(1,1)); // "" empty string
System.out.println(s.substring(3, 2)); // ❌ Exception: start index (3) > end index (2)
System.out.println("abcd".substring(2, 4)); // "cd" — includes indexes 2 and 3; 4 is excluded but legal here
System.out.println("abcd".substring(2, 5)); // ❌ StringIndexOutOfBoundsException (end index 5 is invalid)