Découper une chaîne de caractères paraît simple, jusqu’au moment où un indice décalé provoque une exception ou tronque un caractère. En Java, la méthode substring() permet d’extraire rapidement une portion de texte, à condition de bien comprendre ses indices, ses limites et les cas où une autre méthode convient mieux.
Les repères essentiels pour extraire une portion de texte en Java
-
Deux signatures existent avec
substring(beginIndex)etsubstring(beginIndex, endIndex). - L’indice de début est inclus, tandis que l’indice de fin est exclu.
- Un indice invalide déclenche une StringIndexOutOfBoundsException.
- Les chaînes Java sont immutables : l’extraction retourne une nouvelle valeur sans modifier l’original.
- Pour des caractères Unicode complexes, il faut parfois raisonner en points de code plutôt qu’en simples indices.

Comprendre les deux formes de substring
La méthode appartient à la classe String et sert à récupérer une sous-chaîne à partir d’un texte existant. Dans mes propres exemples Java, je commence presque toujours par visualiser les positions des caractères, car c’est le moyen le plus rapide d’éviter les erreurs d’indice.
String texte = "Bonjour Java";
String partie1 = texte.substring(8);
String partie2 = texte.substring(0, 7);
System.out.println(partie1); // Java
System.out.println(partie2); // Bonjour
La première forme reçoit uniquement beginIndex. Elle extrait le texte depuis cet indice jusqu’à la fin de la chaîne. La seconde reçoit deux indices et récupère les caractères situés entre le début inclus et la fin exclue.
String langage = "Java";
String resultat = langage.substring(1, 3);
System.out.println(resultat); // av
Dans cet exemple, l’indice 1 correspond à a, tandis que l’indice 3 marque la limite après v. Le caractère placé à la position finale n’est donc jamais inclus. Cette règle peut sembler déroutante au début, mais elle rend les calculs de longueur beaucoup plus cohérents, car la taille de l’extrait vaut simplement endIndex - beginIndex.
Lire correctement les indices et les limites
Java numérote les caractères à partir de 0. Pour la chaîne "Java", J se trouve à la position 0, a à la position 1, v à la position 2 et a à la position 3. La longueur totale est 4, ce qui signifie que l’indice de fin peut aller jusqu’à 4, sans désigner un caractère concret.
| Expression | Résultat | Explication |
|---|---|---|
"Java".substring(0) |
"Java" |
Extrait toute la chaîne |
"Java".substring(1) |
"ava" |
Commence à l’indice 1 |
"Java".substring(0, 2) |
"Ja" |
L’indice 2 est exclu |
"Java".substring(4) |
"" |
Retourne une chaîne vide |
Les erreurs apparaissent lorsque le début est négatif, dépasse la longueur du texte, ou lorsque la fin est supérieure à cette longueur. Java refuse également un intervalle où le début est supérieur à la fin. Selon le cas, le programme lève une exception de type StringIndexOutOfBoundsException ou une exception d’index équivalente.
String code = "ABC";
String erreur1 = code.substring(4); // Exception
String erreur2 = code.substring(2, 1); // Exception
String erreur3 = code.substring(-1); // Exception
Pour du texte fourni par un utilisateur, je ne passe jamais directement des indices non contrôlés à substring(). Une vérification simple rend le comportement prévisible et évite qu’une saisie inattendue fasse tomber tout le traitement.
int debut = 2;
int fin = 8;
if (debut >= 0 && fin <= texte.length() && debut <= fin) {
String extrait = texte.substring(debut, fin);
}
Extraire un texte dans des cas concrets
Récupérer une extension de fichier
Pour extraire une extension, je préfère d’abord rechercher le dernier point avec lastIndexOf(). Cette approche fonctionne mieux pour des noms comme archive.backup.zip, car elle conserve uniquement zip.
String nomFichier = "archive.backup.zip";
int positionPoint = nomFichier.lastIndexOf('.');
String extension = positionPoint >= 0
? nomFichier.substring(positionPoint + 1)
: "";
System.out.println(extension); // zip
La condition est importante. Sans elle, un fichier dépourvu d’extension pourrait produire un résultat incorrect ou une logique difficile à maintenir. Pour une application réelle, je traite aussi séparément les noms qui se terminent par un point ou qui commencent par un point, comme certains fichiers cachés.
Isoler une partie d’un identifiant
Une autre utilisation fréquente consiste à récupérer un préfixe ou un segment dans un identifiant. Ici, la lisibilité compte davantage que la compacité, surtout si la valeur sera modifiée plus tard.
String reference = "FR-2026-0048";
String pays = reference.substring(0, 2);
String annee = reference.substring(3, 7);
String numero = reference.substring(8);
System.out.println(pays); // FR
System.out.println(annee); // 2026
System.out.println(numero); // 0048
Ce code repose sur un format fixe. Si les données peuvent contenir des séparateurs variables ou des segments manquants, split() ou un parseur dédié sera souvent plus sûr. J’évite de multiplier les indices codés en dur dès que le format devient évolutif.
Lire aussi : À quoi sert Java ? Usages réels et pertinence en 2026
Afficher un aperçu limité
Pour afficher un extrait de description, il est courant de limiter le texte à un nombre maximal de caractères. La borne doit cependant être comparée à la longueur réelle de la chaîne.
String description = "Une description assez longue pour être abrégée.";
int limite = 20;
String apercu = description.length() > limite
? description.substring(0, limite) + "..."
: description;
System.out.println(apercu);
Cette technique convient à un aperçu simple, mais elle peut couper un mot au milieu. Dans une interface destinée au public, je préfère parfois rechercher le dernier espace avant la limite afin d’obtenir un rendu plus naturel.
Choisir entre substring, split et les expressions régulières
substring() est idéale lorsque les positions sont connues ou calculées précisément. Elle devient moins adaptée quand il faut découper un texte selon un séparateur, reconnaître plusieurs formats ou valider une structure complexe.
| Besoin | Méthode conseillée | Pourquoi |
|---|---|---|
| Extraire une plage d’indices | substring() |
Simple et lisible |
| Séparer une chaîne avec un délimiteur | split() |
Adapté aux virgules, espaces ou tirets |
| Vérifier un préfixe ou un suffixe |
startsWith() ou endsWith()
|
Évite une extraction inutile |
| Rechercher une structure variable |
Pattern et Matcher
|
Utile pour les formats complexes |
| Traiter plusieurs modifications | StringBuilder |
Évite de créer trop de chaînes intermédiaires |
Par exemple, pour une adresse e-mail, chercher directement le caractère @ est généralement plus clair que de supposer une position fixe.
String email = "contact@exemple.fr";
int positionArobase = email.indexOf('@');
if (positionArobase > 0) {
String utilisateur = email.substring(0, positionArobase);
String domaine = email.substring(positionArobase + 1);
}
Je ne présenterais toutefois pas ce fragment comme une validation complète d’adresse e-mail. Il montre uniquement comment extraire deux segments. Pour valider réellement une adresse, il faut une règle métier plus précise et gérer les cas particuliers.
Éviter les erreurs liées à l’immutabilité et à Unicode
Une chaîne Java est immuable. Cela signifie que substring() ne modifie jamais la variable d’origine, même si le résultat est stocké dans une autre variable. Cette distinction est souvent oubliée dans les premiers programmes.
String original = "Bonjour";
String extrait = original.substring(0, 3);
System.out.println(original); // Bonjour
System.out.println(extrait); // Bon
Si je veux remplacer la valeur initiale, je dois explicitement la réaffecter. Le fait d’appeler la méthode seul ne produit aucun changement visible dans la variable originale.
String texte = "Bonjour";
texte.substring(0, 3);
System.out.println(texte); // Bonjour
texte = texte.substring(0, 3);
System.out.println(texte); // Bon
Autre point plus subtil, les indices de String reposent sur des unités UTF-16. Pour les caractères représentés par une paire spéciale, comme certains emojis, couper au milieu peut produire un texte invalide ou visuellement surprenant.
String texte = "A😀B";
System.out.println(texte.length()); // 4
Le symbole visible entre A et B occupe ici deux unités Java. Lorsque le traitement doit respecter les caractères Unicode réels, j’utilise plutôt codePoints(), offsetByCodePoints() ou une bibliothèque spécialisée. Pour du texte technique limité à l’alphabet courant, substring() reste généralement parfaitement appropriée.
Adopter une méthode fiable dans son code
La règle la plus pratique consiste à calculer les bornes à partir du contenu, puis à les contrôler avant l’extraction. Une petite méthode utilitaire peut protéger les appels répétés, mais elle doit avoir un comportement clair lorsque les indices sont invalides.
static String extraireSiValide(String texte, int debut, int fin) {
if (texte == null) {
return "";
}
if (debut < 0 || fin > texte.length() || debut > fin) {
return "";
}
return texte.substring(debut, fin);
}
Retourner une chaîne vide n’est pas toujours le meilleur choix. Dans une logique métier stricte, je préfère parfois lancer une exception explicite, car masquer une donnée incorrecte rend le diagnostic plus difficile. Le choix dépend donc du contrat de la méthode, et non d’une règle universelle.
Pour les performances, une extraction occasionnelle coûte peu et reste très lisible. En revanche, créer des milliers de sous-chaînes dans une boucle peut augmenter les allocations mémoire. Dans ce cas, je mesure d’abord avec un profilage réel avant de remplacer le code par un StringBuilder ou une autre structure, car l’optimisation prématurée rend souvent le traitement moins compréhensible sans gain mesurable.
Le bon réflexe avant chaque extraction
Pour extraire une portion de texte en Java, je vérifie trois éléments. Je confirme d’abord que l’indice de départ correspond bien au caractère voulu, puis que la borne finale est exclusive, et enfin que les données peuvent réellement respecter le format attendu.
substring() reste une méthode courte, rapide et très efficace pour les découpages déterministes. Dès que le texte devient variable, multilingue ou structuré par des séparateurs, je choisis un outil adapté plutôt que de forcer une succession d’indices. Ce simple réflexe évite la plupart des bugs et produit un code beaucoup plus facile à relire.