Formatage de chaînes en Java
Formatez des chaînes Java avec String.format et printf grâce aux spécificateurs %s, %d, %f et %n.
La concaténation (+) convient aux chaînes courtes et simples. Dès que vous souhaitez afficher un nombre avec un nombre précis de décimales, aligner des colonnes par rembourrage, intégrer une date avec une mise en forme cohérente, ou formater des valeurs plutôt que de simplement les coller, vous faites appel à l'API de style printf que Java a empruntée au C.
Il existe trois points d'entrée étroitement liés, que vous rencontrerez tous dans du vrai code :
String.format(fmt, args...)— renvoie uneStringformatée."...".formatted(args...)— forme instance ajoutée en Java 15. Résultat identique, plus adaptée au chaînage.System.out.printf(fmt, args...)— imprime directement dans unPrintStream(ou toutFormatter).
Tous trois partagent la même syntaxe de spécificateurs de format. Apprenez-la une fois.
Spécificateurs de format
Un spécificateur a la forme %[flags][width][.precision]conversion. La lettre de conversion est la seule partie obligatoire. Le reste règle la largeur, l'alignement, le rembourrage et la précision.
String s = String.format("%-10s | %5d | %8.2f", "apples", 42, 3.14159);
// "apples | 42 | 3.14"Les conversions les plus utiles :
| Conversion | Argument | Signification |
|---|---|---|
%s | quelconque | toString() de la valeur |
%d | entier | entier décimal |
%f | virgule flottante | décimal à virgule fixe |
%e | virgule flottante | notation scientifique |
%g | virgule flottante | le plus court entre %e et %f |
%x, %o | entier | hexadécimal / octal |
%c | caractère | caractère unique |
%b | quelconque | true/false (null → "false") |
%n | aucun | séparateur de ligne adapté à la plateforme |
%% | aucun | un % littéral |
%t... | date/heure | toute une famille — %tF, %tT, etc. |
La largeur rembourre la sortie jusqu'à au moins N caractères ; la précision signifie « chiffres décimaux » pour les flottants et « caractères maximum » pour les chaînes.
Flags : alignement, signe, rembourrage zéro, groupement
Quelques flags se placent entre % et la largeur :
-— aligner à gauche dans la largeur. Par défaut, alignement à droite.0— rembourrer avec des zéros jusqu'à la largeur (conversions numériques uniquement).+— toujours afficher un signe sur les nombres (+42,-7).(espace) — afficher un espace avant les nombres positifs, comme+mais avec un blanc.,— grouper les chiffres avec le séparateur de milliers de la locale.(— encadrer les nombres négatifs entre parenthèses, style comptabilité.
String.format("%08d", 42); // "00000042"
String.format("%,d", 1234567); // "1,234,567"
String.format("%+.2f", 3.14159); // "+3.14"
String.format("%-10s|", "hi"); // "hi |"Largeur et précision
La largeur est la largeur de champ minimale — si la valeur formatée est plus large, rien n'est tronqué.
La précision a des significations différentes selon les conversions :
%.3f— trois chiffres après la virgule.%.10s— tronquer la chaîne à au plus 10 caractères.%.4e— quatre chiffres de précision de mantisse.
Combiner largeur et précision est courant lorsqu'on veut aligner des colonnes et arrondir des nombres :
String.format("%10.4f", Math.PI); // " 3.1416"
String.format("%-10.4s", "abcdef"); // "abcd "%n vs \n
%n émet le séparateur de ligne adapté à la plateforme : "\n" sous Unix, "\r\n" sous Windows. \n représente toujours exactement un octet. Pour les fichiers et les sorties de protocole où la fin de ligne compte précisément, préférez \n et choisissez-le consciemment. Pour une sortie console censée s'afficher correctement sur n'importe quel OS où tourne la JVM, %n est le choix le plus sûr.
Indices d'arguments : réutilisation et réordonnancement
Un spécificateur de la forme %N$... fait référence au N-ième argument (base 1). Utile lorsqu'une valeur apparaît plusieurs fois dans un gabarit, ou lorsque l'ordre de lecture naturel diffère de l'ordre des arguments :
String.format("%1$s, %1$s, %1$s!", "go"); // "go, go, go!"
String.format("%2$s before %1$s", "lunch", "tea"); // "tea before lunch"C'est le bon outil lors de la localisation des gabarits — différentes langues placent les noms à des positions différentes, et un traducteur peut réorganiser les espaces réservés sans toucher au site d'appel.
La locale compte pour les nombres et les dates
Le formatage des nombres respecte la locale par défaut de la JVM, sauf si vous la remplacez. En en-US vous obtenez 3.14 ; en de-DE vous obtenez 3,14 ; en fr-FR les milliers sont groupés par une espace insécable. Pour une sortie destinée à des humains, c'est généralement ce que vous voulez. Pour les formats de données — JSON, CSV, fichiers journaux, tout ce qui est lisible par une machine — c'est un désastre qui attend un déploiement à Francfort.
Passez toujours une locale explicitement pour les sorties lisibles par une machine :
String json = String.format(Locale.ROOT, "{\"price\": %.2f}", 19.95);
// "{\"price\": 19.95}" — always, regardless of JVM localeLocale.ROOT signifie « pas de formatage spécifique à la locale » — point comme décimale, pas de groupement. Locale.US est l'autre choix courant dans le même but. Le danger est de ne pas passer de locale et de faire des suppositions.
Formatage date/heure
%t est une méta-conversion : la lettre qui suit choisit le champ. Le même argument Date, Calendar, Long (millis) ou java.time.temporal.TemporalAccessor peut être formaté de nombreuses façons :
LocalDateTime now = LocalDateTime.of(2026, 5, 29, 14, 30, 15);
String.format("%tF", now); // "2026-05-29" — ISO date
String.format("%tT", now); // "14:30:15" — 24-hour time
String.format("%tA", now); // "Friday" — locale-dependent
String.format("%1$tF %1$tT", now); // "2026-05-29 14:30:15"Pour tout ce qui va au-delà d'un formatage rapide, l'API java.time.format.DateTimeFormatter est plus flexible et consciente de la locale — mais %tF et ses dérivés restent pratiques dans les lignes de journal.
Pièges courants
- Mauvaise conversion pour le type.
String.format("%d", 3.14)lèveIllegalFormatConversionExceptionà l'exécution —%dattend un entier,%fattend un flottant. Le compilateur ne peut pas le vérifier. - Arguments manquants. Oublier un argument de remplacement lève
MissingFormatArgumentException. - Décimale dépendante de la locale dans une sortie machine. Traité ci-dessus.
%ssurnull. Produit"null". Acceptable dans les journaux, embarrassant dans une sortie visible par l'utilisateur.- Utiliser
+pour des nombres formatés."Price: " + 19.95donne"Price: 19.95", mais"Price: " + 0.1 + 0.2donne"Price: 0.10.2", pas"Price: 0.3"— c'est de la concaténation, pas une addition.
Un exemple complet
Un petit formateur de résumé de commande qui met en pratique la largeur, la précision, l'alignement, le groupement, la locale et la conversion de date %t. La sortie est un rapport en deux colonnes bien ordonné — le genre de chose que vous construiriez autrement à la main avec des helpers padLeft.
Deux points à noter : le %<tT dans la ligne « Placed » réutilise l'argument précédent (< est le flag de référence arrière), évitant un second placedAt redondant. Et la ligne JSON utilise Locale.ROOT — le même code sur une JVM allemande émet tout de même 1339.43, et non 1339,43, ce qu'un analyseur JSON attend exactement.
Et ensuite
Construire des chaînes représente la moitié du travail. Les comparer — égalité, ordre, normalisation de casse, la différence entre == et equals — est l'autre moitié et une source fréquente de bugs subtils. Continuez avec Comparaison de chaînes Java.