W3docs

Conversiones de String en Java

Convierte entre strings y primitivos en Java — Integer.parseInt, Double.parseDouble, String.valueOf y más.

La mayoría de los datos llegan como texto y la mayoría de los datos salen como texto. Entre esos dos límites suelen vivir como algo más útil — un int, un double, un boolean, un LocalDate. Este capítulo trata sobre las dos direcciones de conversión entre String y los tipos primitivos, los tipos envolventes y los arrays de caracteres.

Hay un pequeño vocabulario que vale la pena memorizar; una vez que lo conoces, la respuesta a "¿cómo convierto este string en un X?" es siempre una sola línea.

String → primitivo: la familia parse...

Cada clase envolvente tiene un método estático que recibe un String y devuelve el primitivo correspondiente:

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

Estas son las herramientas estándar. Lanzan NumberFormatException para entradas que no se pueden parsear — incluyendo null, strings vacíos, strings con espacios en blanco, decimales con formato regional como "3,14" y valores fuera de rango.

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

Integer.parseInt acepta un segundo argumento opcional para 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 lee los dígitos literales en la base que se le pasa; no entiende los prefijos del código fuente como 0x ni un 0 inicial para octal. Por eso Integer.parseInt("0777", 8) está bien — el 0 inicial es simplemente otro dígito octal — pero Integer.parseInt("0x1A", 16) lanza una excepción, porque x no es un dígito en base 16. Elimina cualquier prefijo tú mismo antes de parsear.

Para interpretación sin signo del bit más significativo en valores de 32 y 64 bits, el JDK añade Integer.parseUnsignedInt y Long.parseUnsignedLong.

String → envolvente: valueOf vs parse...

El valueOf estático en cada clase envolvente hace el mismo parseo pero devuelve el tipo envolvente:

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

Los dos difieren en tres puntos que a veces importan:

  • Tipo de retorno. parseIntint, valueOfInteger. Elige el que necesite tu destinatario.
  • Caché. Integer.valueOf(int) y Long.valueOf(long) almacenan en caché números pequeños (-128..127 por defecto), devolviendo la misma instancia de Integer para llamadas repetidas. parseInt devuelve un primitivo, por lo que el caché no aplica — pero cuando igual ibas a hacer boxing del resultado, valueOf es más económico.
  • Comportamiento en desbordamiento. Idéntico — ambos lanzan NumberFormatException.

Regla general: si quieres un primitivo, usa parseInt; si quieres un envolvente, usa valueOf. No escribas Integer.valueOf(Integer.parseInt(s)) — eso son dos parseos de código para un solo parseo de resultado.

Primitivo → String: String.valueOf y similares

La dirección inversa tiene dos herramientas bien nombradas:

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

Cada clase envolvente también tiene un toString que recibe el primitivo:

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

Y por supuesto, la concatenación con "" también funciona:

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

String.valueOf es el más general y el estilo más defendible — nunca lanza excepción con null y maneja todos los primitivos más Object. Para formateo numérico donde necesitas ancho, signo, agrupación o decimales con formato regional, recurre a String.format.

Strings y chars

Un char es un primitivo (una unidad de código UTF-16); un String es una secuencia de ellos. Conversiones en ambas direcciones:

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() siempre devuelve un array nuevo y modificable. Es la herramienta adecuada cuando necesitas mutar caracteres (por ejemplo, para limpiar un buffer de contraseña) — el propio String no puede darte una vista mutable.

Strings y bytes

Los bytes son el formato de red; los strings son la forma en memoria. La conversión siempre implica un charset, y la respuesta correcta es siempre pasarlo explícitamente:

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

Las sobrecargas sin argumentos (getBytes(), new String(bytes)) usan el charset por defecto de la JVM, que depende de la plataforma y es una fuente constante de errores del tipo "funciona en mi máquina". Siempre pasa un Charset. UTF-8 es el valor por defecto correcto para código nuevo; los sistemas heredados a veces necesitan Latin-1 o una de las páginas de código Windows.

Conversiones que no existen

Algunas conversiones que la gente busca pero que no están disponibles:

  • intchar por valor de dígito. (char) 5 es el carácter de control en el punto de código 5, no '5'. Usa Character.forDigit(5, 10) o (char) ('0' + 5).
  • charint por valor de dígito. (int) '5' es 53, no 5. Usa Character.digit('5', 10) o '5' - '0'.
  • String → numérico con valor por defecto en caso de error. Java no incluye un parseIntOrDefault. La versión idiomática es un pequeño helper:
static int parseIntOr(String s, int fallback) {
  try { return Integer.parseInt(s); }
  catch (NumberFormatException e) { return fallback; }
}

La conversión no es validación

El mayor error con la conversión de string a primitivo es tratar un parseo exitoso como una validación exitosa. Integer.parseInt("0") devuelve 0 para cualquier entrada que el usuario escriba como cero, incluyendo "0", "00", "+0" y "-0" — todas las cuales parsean al mismo valor. Si te importa que la entrada sea canónica, parsea y luego convierte de vuelta:

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

Para entradas numéricas de formularios orientados al usuario, valida primero el formato (regex, longitud, caracteres permitidos) y luego parsea. No te apoyes en el parser para determinar si la entrada era razonable.

Un ejemplo completo

Un programa que convierte en ambas direcciones para los tipos más comunes, incluyendo un helper robusto con valor por defecto en caso de error, un viaje de ida y vuelta en hexadecimal y un viaje de ida y vuelta bytes/string con UTF-8.

java— editable, runs on the server

Tres detalles a observar en la salida. El string héllo va y viene a través de UTF-8 sin problemas — cinco caracteres se convierten en seis bytes (la é ocupa dos), y los bytes resultantes se parsean de vuelta en los mismos cinco caracteres. String.valueOf((Object)null) produce "null" en lugar de lanzar una excepción — eso es deliberado; es por qué "x = " + nullable no explota. Y el helper parseIntOr maneja entradas incorrectas, entradas con espacios y entradas null sin que el sitio de llamada tenga que saberlo.

¿Qué sigue?

El capítulo que cierra la Parte 9 cubre los dos métodos más usados de "string de entrada, lista de salida / lista de entrada, string de salida" en la biblioteca estándar — y las variantes basadas en regex que subyacen a ellos. Continúa en Java String split() y join().

Práctica

Práctica
¿Cuál es la diferencia entre `Integer.parseInt('42')` e `Integer.valueOf('42')`?
¿Cuál es la diferencia entre `Integer.parseInt('42')` e `Integer.valueOf('42')`?
Was this page helpful?