W3docs

Conversions de chaînes Java

Convertissez entre chaînes Java et types primitifs — Integer.parseInt, Double.parseDouble, String.valueOf, et plus encore.

La plupart des données arrivent sous forme de texte et en repartent sous forme de texte. Entre ces deux frontières, elles vivent généralement sous une forme plus utile — un int, un double, un boolean, une LocalDate. Ce chapitre traite des deux directions de conversion entre String et les types primitifs, les types enveloppes, et les tableaux de caractères.

Il y a un petit vocabulaire à mémoriser ; une fois que vous le connaissez, la réponse à « comment je transforme cette chaîne en X » est une ligne de code à chaque fois.

String → primitif : la famille parse...

Chaque classe enveloppe possède une méthode statique qui prend une String et retourne le primitif correspondant :

int    i = Integer.parseInt("42");
long   l = Long.parseLong("9999999999");
double d = Double.parseDouble("3.14");
float  f = Float.parseFloat("3.14");
short  s = Short.parseShort("32000");
byte   b = Byte.parseByte("127");
boolean ok = Boolean.parseBoolean("true");  // any case-insensitive "true"; everything else → false

Ce sont les outils standard. Ils lèvent une NumberFormatException pour une entrée qui ne peut pas être analysée — y compris null, les chaînes vides, les chaînes avec des espaces, les décimales spécifiques à une locale comme "3,14", et les valeurs hors plage.

Integer.parseInt(" 42 ");      // NumberFormatException — trim first
Integer.parseInt("3.0");       // NumberFormatException — that's a double
Integer.parseInt("1234567890123"); // NumberFormatException — overflows int

Integer.parseInt accepte un deuxième argument optionnel pour la base :

Integer.parseInt("ff", 16);    // 255
Integer.parseInt("1010", 2);   // 10
Integer.parseInt("777", 8);    // 511 — the radix is the second arg, not a prefix
Integer.parseInt("0x1A", 16);  // NumberFormatException — no "0x" prefix; pass just "1A"

parseInt lit les chiffres littéraux dans la base que vous passez ; il ne comprend pas les préfixes du code source comme 0x ou un 0 initial pour l'octal. Ainsi, Integer.parseInt("0777", 8) fonctionne — le 0 initial est simplement un autre chiffre octal — mais Integer.parseInt("0x1A", 16) lève une exception, car x n'est pas un chiffre en base 16. Retirez tout préfixe vous-même avant d'analyser.

Pour l'interprétation non signée du bit de poids fort sur des valeurs 32 et 64 bits, le JDK ajoute Integer.parseUnsignedInt et Long.parseUnsignedLong.

String → enveloppe : valueOf vs parse...

Le valueOf statique sur chaque classe enveloppe effectue la même analyse mais retourne le type enveloppe :

Integer n = Integer.valueOf("42");     // Integer, not int
Double d  = Double.valueOf("3.14");    // Double, not double

Les deux diffèrent en trois points qui ont leur importance à l'occasion :

  • Type de retour. parseIntint, valueOfInteger. Choisissez celui que votre destination attend.
  • Mise en cache. Integer.valueOf(int) et Long.valueOf(long) mettent en cache les petits nombres (-128..127 par défaut), retournant la même instance Integer pour des appels répétés. parseInt retourne un primitif, donc la mise en cache n'a pas d'importance — mais quand vous allez de toute façon boxer le résultat, valueOf est moins coûteux.
  • Comportement en cas de dépassement. Identique — les deux lèvent NumberFormatException.

Règle empirique : si vous voulez un primitif, utilisez parseInt ; si vous voulez une enveloppe, utilisez valueOf. N'écrivez pas Integer.valueOf(Integer.parseInt(s)) — c'est deux analyses de code pour un résultat d'une seule analyse.

Primitif → String : String.valueOf et ses variantes

La direction inverse dispose de deux outils bien nommés :

String s1 = String.valueOf(42);              // "42"
String s2 = String.valueOf(3.14);            // "3.14"
String s3 = String.valueOf(true);            // "true"
String s4 = String.valueOf('a');             // "a"
String s5 = String.valueOf(new char[]{'h','i'}); // "hi"
String s6 = String.valueOf((Object) null);   // "null"  — NOT an NPE

Chaque classe enveloppe possède également un toString qui prend le primitif :

Integer.toString(42);          // "42"
Integer.toString(255, 16);     // "ff"   — radix overload
Long.toString(123456789L);     // "123456789"
Double.toString(3.14);         // "3.14"

Et bien sûr, la concaténation avec "" fonctionne :

String s = "" + 42;            // "42"

String.valueOf est le plus général et le plus défendable stylistiquement — il ne lève jamais d'exception sur null et gère tous les primitifs ainsi que les Object. Pour le formatage numérique où vous avez besoin de largeur, de signe, de regroupement, ou de décimales sensibles à la locale, utilisez plutôt String.format.

Chaînes et caractères

Un char est un primitif (une unité de code UTF-16) ; une String est une séquence de ces unités. Conversions dans les deux directions :

String  s   = String.valueOf('a');       // "a"
char    c1  = "abc".charAt(0);           // 'a'
char[]  arr = "abc".toCharArray();       // ['a', 'b', 'c']
String  s2  = new String(arr);           // "abc"
String  s3  = new String(arr, 1, 2);     // "bc" — offset + count

String.toCharArray() retourne toujours un tableau frais et modifiable. C'est l'outil approprié quand vous avez besoin de muter des caractères (par exemple pour effacer un tampon de mot de passe) — String lui-même ne peut pas vous offrir de vue mutable.

Chaînes et octets

Les octets sont le format de transmission ; les chaînes sont la forme en mémoire. La conversion implique toujours un jeu de caractères, et la bonne réponse est toujours de le passer explicitement :

byte[] bytes = "héllo".getBytes(StandardCharsets.UTF_8);
String back  = new String(bytes, StandardCharsets.UTF_8);

Les surcharges sans argument (getBytes(), new String(bytes)) utilisent le jeu de caractères par défaut de la JVM, qui dépend de la plateforme et constitue une source constante de bugs du type « ça marche sur ma machine ». Passez toujours un Charset. UTF-8 est la valeur par défaut appropriée pour le nouveau code ; les systèmes hérités ont parfois besoin de Latin-1 ou d'une des pages de code Windows.

Conversions qui n'existent pas

Quelques conversions que les gens cherchent et qui ne sont pas disponibles :

  • intchar par valeur de chiffre. (char) 5 est le caractère de contrôle au point de code 5, pas '5'. Utilisez Character.forDigit(5, 10) ou (char) ('0' + 5).
  • charint par valeur de chiffre. (int) '5' vaut 53, pas 5. Utilisez Character.digit('5', 10) ou '5' - '0'.
  • String → numérique avec valeur par défaut en cas d'échec. Java ne fournit pas de parseIntOrDefault. La version idiomatique est un petit auxiliaire :
static int parseIntOr(String s, int fallback) {
  try { return Integer.parseInt(s); }
  catch (NumberFormatException e) { return fallback; }
}

La conversion n'est pas une validation

La plus grande erreur avec la conversion chaîne → primitif est de traiter une analyse réussie comme une validation réussie. Integer.parseInt("0") retourne 0 pour toute entrée que l'utilisateur tape comme zéro, y compris "0", "00", "+0", et "-0" — tous analysés à la même valeur. Si vous tenez à ce que l'entrée soit canonique, analysez puis reconvertissez :

int v = Integer.parseInt(input);
if (!Integer.toString(v).equals(input)) {
  throw new IllegalArgumentException("non-canonical integer: " + input);
}

Pour les entrées numériques provenant de formulaires destinés aux humains, validez le format en premier (regex, longueur, caractères autorisés), puis analysez. Ne comptez pas sur l'analyseur pour vous dire si l'entrée était raisonnable.

Un exemple concret

Un programme qui convertit dans les deux directions pour les types les plus courants, y compris un auxiliaire robuste avec valeur par défaut en cas d'échec, un aller-retour hexadécimal, et un aller-retour octet/chaîne avec UTF-8.

java— editable, runs on the server

Trois détails à noter dans la sortie. La chaîne héllo effectue un aller-retour propre à travers UTF-8 — cinq caractères deviennent six octets (le é en prend deux), et les octets résultants se retrouvent analysés en cinq caractères identiques. String.valueOf((Object)null) produit "null" plutôt que de lever une exception — c'est délibéré ; c'est pourquoi "x = " + nullable ne plante pas. Et l'auxiliaire parseIntOr gère les entrées incorrectes, les entrées avec espaces, et les entrées null sans que votre site d'appel ait besoin de le savoir.

La suite

Le chapitre qui clôt la Partie 9 couvre les deux méthodes les plus utilisées « chaîne en entrée, liste en sortie / liste en entrée, chaîne en sortie » de la bibliothèque standard — et les variantes à base de regex qui se trouvent en dessous. Continuez vers Java String split() et join().

Exercices

Pratique
Quelle est la différence entre `Integer.parseInt('42')` et `Integer.valueOf('42')` ?
Quelle est la différence entre `Integer.parseInt('42')` et `Integer.valueOf('42')` ?
Was this page helpful?