Conversión entre número y cadena en Java: parseInt, valueOf, toString y errores comunes

目次

1. Conocimientos básicos para convertir entre números y cadenas en Java

Al desarrollar en Java, inevitablemente te encontrarás con situaciones como “datos que parecen un número pero se manejan como cadena” o “valores recibidos como cadenas que deseas calcular como números”. Por ejemplo, entradas de formularios, importaciones CSV, respuestas de API y salida de logs a menudo llegan como cadenas aunque parezcan numéricos.
En esta sección organizaremos por qué la conversión es necesaria y los puntos con los que los principiantes suelen tener dificultades.

1.1 Por qué la conversión se vuelve necesaria

Los programas Java manejan el tipo de dato (type) de forma explícita. Sin embargo, las entradas y salidas de datos del mundo real tienden a convertirse en “cadenas”, como por ejemplo:

  • Entrada del usuario: aunque escribas “123” en un cuadro de texto, lo que el programa recibe es básicamente una cadena
  • Archivos (CSV / JSON / archivos de configuración): al leerlos, a menudo obtienes valores como cadenas
  • HTTP/API: muchos valores se pasan como cadenas (o el tipo JSON puede ser ambiguo)
  • Visualización y logs: en lugar de imprimir números tal cual, es común convertirlos a cadenas y formatearlos

Por ello, en el trabajo real se producen dos direcciones de conversión con frecuencia:

  • Número → Cadena: visualización en UI, logs, mensajes, concatenación, etc.
  • Cadena → Número: cálculos, comparaciones, verificaciones de rango, agregaciones, etc.

Lo importante aquí es: aunque parezca numérico, tipos diferentes significan cosas diferentes.

  • "10" (cadena) y 10 (número) pueden verse iguales, pero son tipos diferentes en el código
  • La cadena "10" + "2" se convierte en "102" (concatenación)
  • El número 10 + 2 se convierte en 12 (suma)

Errores como “creí que estaba sumando, pero se convirtió en concatenación de cadenas” ocurren fácilmente si no mantienes esta distinción presente.

1.2 Java es estricto con los tipos

Java es un lenguaje de tipado estático, por lo que las operaciones con tipos incompatibles generalmente resultan en un error de compilación. Esto mejora la seguridad, pero al pasar entre tipos diferentes como cadenas y números, necesitas conversiones adecuadas.

Por ejemplo, si intentas usar directamente una cadena como número, obtendrás un error.

  • Quieres calcular con la cadena "123" como un int → Debes convertirla a int antes de usarla

Además, Java tiene dos tipos de datos numéricos: tipos primitivos y clases contenedoras (wrapper), lo que puede ser una fuente frecuente de confusión.

  • Tipos primitivos: int, long, double, etc. (ligeros, números básicos)
  • Clases contenedoras: Integer, Long, Double, etc. (números manejados como objetos)

Por ejemplo, Integer.valueOf("123") devuelve un Integer (objeto), mientras que Integer.parseInt("123") devuelve un int (primitivo).
Abordaremos esta diferencia con más detalle en la siguiente sección, pero los principiantes a menudo se quedan atascados porque “la misma conversión parece devolver tipos diferentes”.

1.3 Diferencias entre conversión automática y explícita

Cuando escuchas “conversión”, podrías imaginar que Java la maneja automáticamente. En realidad, existen comportamientos que parecen conversiones automáticas en algunos casos.

Un ejemplo común es la concatenación de cadenas.

  • Si escribes "Total: " + 10, el 10 parece convertirse automáticamente en una cadena

Sin embargo, aunque sea conveniente, esto también puede producir resultados no deseados.

  • "10" + 2"102" (concatenación de cadenas, no suma numérica)

Así, Java tiene casos donde los valores se convierten implícitamente a cadena, pero Cadena → Número básicamente no se convierte automáticamente.
En otras palabras:

  • Número → Cadena: puede ocurrir implícitamente en algunos contextos (como la concatenación)
  • Cadena → Número: siempre requiere conversión explícita (como parseInt)

Recordar esto te mantendrá a salvo.

Además, al convertir cadenas a números, las entradas no siempre son válidas.

  • Cadena vacía ""
  • Espacios " 123 "
  • Separador de miles "1,000"
  • Intentar convertir un decimal "12.34" a int
  • Caracteres no numéricos "12a"

En tales casos, se producirá una excepción en tiempo de ejecución (normalmente NumberFormatException).
En sistemas del mundo real, es fundamental diseñar asumiendo que “puede llegar una entrada no válida”.

2. Cómo convertir números a cadenas

En esta sección explicaremos las formas más comunes de convertir números en cadenas en Java, así como cómo elegir entre ellas.
Esta conversión se utiliza constantemente en registros, salida de UI y construcción de mensajes.

2.1 Usando String.valueOf() (la más común)

Para convertir números a cadenas, el enfoque más seguro y recomendado es String.valueOf().

int i = 100;
String s = String.valueOf(i);

Admite no solo int sino también long, double, float, boolean y casi todos los tipos primitivos.

double d = 12.34;
String s = String.valueOf(d);

Características clave de este enfoque:

  • Sintaxis consistente y fácil de recordar
  • Funciona tanto con tipos primitivos como con clases wrapper
  • Alta legibilidad
  • Intención clara (“esto es una conversión a cadena”) a simple vista

También convierte de forma segura objetos wrapper.

Integer num = null;
String s = String.valueOf(num); // "null"

Incluso si pasas null, no lanzará un NullPointerException, lo cual es especialmente útil para el registro.

2.2 Usando Integer.toString() / Double.toString()

Cada clase wrapper numérica proporciona un método utilitario toString().

int i = 100;
String s = Integer.toString(i);
double d = 12.34;
String s = Double.toString(d);

Esto funciona correctamente, pero tiene estas características:

  • El método difiere según el tipo (Integer / Double / Long, etc.)
  • Resulta un poco tedioso recordar todos ellos
  • Es menos de propósito general que String.valueOf()

Por lo tanto, en proyectos reales, a menudo se prefiere String.valueOf() a menos que se quiera enfatizar explícitamente un tipo específico.

2.3 Precaución al llamar toString() sobre objetos

También puedes llamar directamente a toString() sobre objetos wrapper o sobre tus propias clases.

Integer i = 100;
String s = i.toString();

Esto funciona, pero debes tener cuidado si es posible que sea null.

Integer i = null;
String s = i.toString(); // NullPointerException

Si el objeto es null, esto provocará un error en tiempo de ejecución.
Por seguridad, String.valueOf() es una mejor opción en casos como:

  • Salida de logs
  • Generación de cadenas de depuración
  • Rutas de código donde puede aparecer null

2.4 ¿Deberías usar “+ «»” para la conversión?

Puede que hayas visto código como este:

int i = 100;
String s = i + "";

Sí, convierte un número en una cadena. Sin embargo, no es un enfoque recomendado.

Razones:

  • La intención no es evidente a simple vista
  • Es ambiguo si se trata de concatenación o de conversión
  • A menudo es rechazado en revisiones de código
  • Es más propenso a generar malentendidos durante cambios futuros

Puede aparecer en demostraciones breves o pruebas rápidas, pero es mejor evitarlo para código mantenible.

2.5 Resumen: cómo elegir la conversión número → cadena

Para evitar confusiones en el trabajo real, recuerda lo siguiente:

  • Opción predeterminada: String.valueOf()
  • Si deseas enfatizar el tipo: Integer.toString() / Double.toString()
  • Llamar a toString() sobre objetos requiere ser consciente de null
  • Evita + «» en principio

3. Cómo convertir cadenas a números

A partir de aquí, explicaremos el tema especialmente importante en proyectos reales: convertir cadenas en números.
Dado que la entrada del usuario y los datos externos no están garantizados como válidos, comprender los métodos de conversión y sus trampas es esencial.

3.1 Usando Integer.parseInt() (lo más básico)

Un método representativo para convertir una cadena en un int es Integer.parseInt().

String s = "123";
int i = Integer.parseInt(s);

Este método devuelve el tipo primitivo int, lo que resulta cómodo cuando deseas realizar cálculos o comparaciones de inmediato.

int total = Integer.parseInt("10") + Integer.parseInt("20");
// total is 30

Sin embargo, pasar cadenas como las siguientes provocará una excepción en tiempo de ejecución.

  • "abc"
  • "" (cadena vacía)
  • "12.3" (decimal)
  • "1,000" (con comas)
    int i = Integer.parseInt("abc"); // NumberFormatException
    

Esta excepción no se detecta en tiempo de compilación—ocurre en tiempo de ejecución, por lo que debes tener cuidado.

3.2 Usando Integer.valueOf()

Integer.valueOf() es otra forma representativa de convertir una cadena en un número.

String s = "123";
Integer i = Integer.valueOf(s);

La mayor diferencia con parseInt() es que el tipo de retorno es Integer (una clase contenedora).

  • parseInt()int
  • valueOf()Integer

Esta diferencia importa en escenarios como:

  • Almacenar valores en colecciones (List / Map)
  • Diseños que manejan null
  • Cuando quieres tratar el valor como un objeto

Internamente, valueOf() también lanza NumberFormatException si la conversión falla.
Por lo que no es “menos propenso a errores” que parseInt().

3.3 Cómo Elegir Entre parseInt y valueOf

Si no estás seguro de cuál usar, estos criterios ayudan:

  • Si el objetivo es cálculo o comparación → parseInt()
  • Si quieres manejarlo como un objeto → valueOf()

Porque Java moderno tiene autoboxing, la diferencia práctica es menor, pero aún es importante desarrollar el hábito de elegir basado en el tipo de retorno.

3.4 Convirtiendo a Otros Tipos Numéricos Como double / long

A menudo necesitas convertir cadenas en tipos distintos a enteros.

long l = Long.parseLong("100000");
double d = Double.parseDouble("12.34");

Las reglas básicas son las mismas:

  • Long.parseLong()long
  • Double.parseDouble()double
  • Float.parseFloat()float

Todos ellos lanzan NumberFormatException si la cadena no se puede convertir.

Una trampa clave es intentar convertir una cadena decimal en un tipo entero:

int i = Integer.parseInt("12.34"); // exception

En ese caso, necesitas un diseño que trate el valor como double desde el principio.

3.5 Ten Cuidado con Espacios Iniciales/Finales

La entrada del usuario a menudo contiene espacios involuntariamente.

String s = " 123 ";
int i = Integer.parseInt(s); // exception

En tales casos, es común usar trim() antes de la conversión.

int i = Integer.parseInt(s.trim());

Sin embargo, incluso después de trim(), ocurrirá una excepción si quedan caracteres no numéricos.

3.6 Resumen: Puntos Clave para la Conversión de Cadena → Número

Para convertir cadenas en números de manera segura, ten en cuenta estos puntos:

  • Siempre desconfía de la entrada externa
  • Diseña asumiendo que pueden ocurrir excepciones
  • Decide el tipo numérico claramente (int / long / double)
  • Preprocesa cuando sea necesario (trim, etc.)

4. Conversiones Usando BigDecimal y BigInteger (Finanzas / Cálculos de Precisión)

Los tipos int y double introducidos hasta ahora son convenientes, pero debes tener cuidado cuando la precisión del cálculo es crítica.
Especialmente para dinero, cantidades y tasas, se usan BigDecimal y BigInteger para evitar problemas de redondeo y precisión.

4.1 Por Qué double No Es Suficiente

Porque double es un tipo de punto flotante, se almacena internamente como una aproximación en binario.
Como resultado, puedes ver un comportamiento como este:

double d = 0.1 + 0.2;
System.out.println(d); // 0.30000000000000004

Esto no es un error—es por diseño.
Puede parecer menor, pero puede ser fatal en casos como:

  • Cálculos de dinero
  • Procesamiento de facturación y liquidación
  • Cálculos acumulativos de tasas de interés o ratios

En tales casos, necesitas un tipo que no introduzca error de punto flotante.

4.2 Conversión de Cadena → Número Usando BigDecimal

Con BigDecimal, la regla es: créalo desde una cadena.

BigDecimal bd = new BigDecimal("12.34");

Un patrón que debes evitar es:

BigDecimal bd = new BigDecimal(12.34); // not recommended

Porque el double original ya contiene un error de aproximación, convertir a BigDecimal llevará ese error adelante.

Recuerda: siempre crea BigDecimal desde una String.

4.3 Conversión de Número a Cadena (BigDecimal)

Para convertir un BigDecimal a una cadena, es común usar toString().

BigDecimal bd = new BigDecimal("12.3400");
String s = bd.toString(); // "12.3400"

Si deseas formato de presentación, puedes usar DecimalFormat, pero la mejor práctica es separar el procesamiento interno del formato de presentación.

4.4 Cuándo usar BigInteger

BigInteger se utiliza para manejar enteros muy grandes.

BigInteger bi = new BigInteger("12345678901234567890");

Casos de uso típicos:

  • Números con una cantidad de dígitos extremadamente grande
  • Representación numérica de IDs o valores hash
  • Cálculos enteros que exceden el rango de long

Es menos frecuente en aplicaciones empresariales típicas, pero es eficaz cuando se deben manejar enteros con límites desconocidos o ilimitados.

4.5 Resumen: Cómo pensar en BigDecimal / BigInteger

  • Dinero / cálculos críticos de precisión → BigDecimal
  • Enteros enormes → BigInteger
  • BigDecimal debe ser creado a partir de una cadena
  • Mantener el formato separado de los cálculos

5. Errores comunes durante la conversión y cómo manejarlos

Al convertir cadenas a números, debes asumir que los errores pueden ocurrir siempre.
En esta sección, organizaremos las excepciones comunes y los enfoques seguros para manejarlas.

5.1 ¿Qué es NumberFormatException?

NumberFormatException es una excepción en tiempo de ejecución que se lanza cuando una cadena no puede interpretarse como un número.

int i = Integer.parseInt("abc"); // NumberFormatException

Esta excepción no se detecta en tiempo de compilación; aparece solo cuando el código se ejecuta. Por lo tanto, si la entrada proviene del exterior (formularios, archivos, APIs, etc.), siempre debes considerarla.

Causas comunes incluyen:

  • Contiene caracteres no numéricos
  • Cadena vacía o nula
  • Intentar convertir un decimal a un tipo entero
  • Contiene comas o símbolos (p.ej., «1,000»)

5.2 Manejo básico con try-catch

El enfoque más básico es usar try-catch para capturar la excepción.

try {
    int i = Integer.parseInt(input);
} catch (NumberFormatException e) {
    // Handling when conversion fails
}

Puntos clave:

  • Maneja de forma fiable la ruta de error
  • Hace explícito el comportamiento de falla
  • Es el más usado en proyectos reales

Combinado con registro y mensajes de error, esto permite un procesamiento seguro.

5.3 Enfoque de prevalidación para evitar excepciones

Separado del manejo de excepciones, también puedes validar si es numérico de antemano.

boolean isNumber = input.matches("\\d+");

Con una expresión regular, puedes comprobar si la cadena contiene solo dígitos. Sin embargo, existen consideraciones importantes:

  • Difícil de soportar decimales y números negativos
  • Puede volverse complejo
  • No brinda una garantía completa

Así que, en la práctica, es realista tratar try-catch como la última red de seguridad.

5.4 Tener cuidado con nulos y cadenas vacías

Antes de la conversión numérica, es importante comprobar si hay nulos o cadenas vacías.

if (input == null || input.isEmpty()) {
    // Error handling
}

Omitir esta comprobación puede provocar excepciones o comportamientos inesperados. Las cadenas vacías son especialmente comunes en entradas de formularios y archivos de configuración.

5.5 Resumen: Cómo pensar en el manejo de errores

  • Considerar la entrada externa como potencialmente inválida
  • Usar try-catch para capturar excepciones de forma fiable
  • Usar prevalidaciones como validación complementaria
  • Excluir nulos y cadenas vacías desde el principio

6. Métodos de conversión recomendados según el caso de uso

Hasta ahora, hemos cubierto las principales formas de convertir entre números y cadenas en Java.
En esta sección, organizaremos la mentalidad basada en casos de uso para que no dudes en el desarrollo real.

6.1 Visualización en UI y salida de logs

Para la visualización en UI y los logs, seguridad y legibilidad son lo primero.

Recomendado:

  • Número → Cadena: String.valueOf()
  • Incluso cuando pueda estar involucrado un objeto, usa String.valueOf()
    log.info("count=" + String.valueOf(count));
    

Aunque null pueda aparecer, previene excepciones.

6.2 Cálculos y Comparaciones

Para cálculos y comparaciones, la regla básica es convertir a tipos numéricos lo antes posible.

  • String → Number: parseInt() / parseLong() / parseDouble()
  • Después de la conversión, completar el procesamiento usando tipos numéricos
    int price = Integer.parseInt(inputPrice);
    int total = price * quantity;
    

Continuar procesando como cadenas puede causar errores sutiles.

6.3 Entradas de Formularios y Procesamiento de Datos Externos

Tratar las entradas de usuario y los datos externos bajo la suposición de que llegarán valores inválidos.

  • Verificaciones de null / cadena vacía
  • Manejo de excepciones mediante try-catch
  • Devolver mensajes de error según sea necesario
    try {
        int age = Integer.parseInt(input);
    } catch (NumberFormatException e) {
        // Input error handling
    }
    

Evite escribir “solo el camino feliz”—piense en los caminos de error primero.

6.4 Dinero y Procesamiento Crítico de Precisión

Para dinero, tasas y otros casos donde el error de punto flotante no es aceptable, use BigDecimal.

  • String → BigDecimal: new BigDecimal(String)
  • Separar el formateo de visualización de los cálculos
    BigDecimal amount = new BigDecimal(inputAmount);
    

La clave es no pasar por double.

6.5 Almacenamiento en Colecciones o Manejo como Objetos

Al almacenar valores en una List o Map, o cuando su diseño maneja null, las clases wrapper son adecuadas.

  • Integer.valueOf()
  • Long.valueOf()
    List<Integer> list = new ArrayList<>();
    list.add(Integer.valueOf("10"));
    

6.6 Resumen por Caso de Uso

Resumido por caso de uso:

  • Visualización / logs → String.valueOf()
  • Cálculos → parseXxx()
  • Dinero / precisión → BigDecimal
  • Entrada externa → diseñar para excepciones
  • Colecciones → valueOf()

7. Errores Comunes y Anti-Patrones

Convertir entre números y cadenas es básico, pero tanto principiantes como desarrolladores experimentados pueden cometer errores.
Esta sección resume anti-patrones que debe evitar en proyectos reales.

7.1 Intentar Calcular Manteniendo Cadenas

Este código parece plausible pero es riesgoso:

String a = "10";
String b = "20";
String result = a + b; // "1020"

Esto no es un cálculo—es concatenación de cadenas.
Para cálculos numéricos, convierta a tipos numéricos primero:

int result = Integer.parseInt(a) + Integer.parseInt(b); // 30

7.2 Sobreusar la Conversión “+ «»”

String s = value + "";

Funciona, pero la intención no es clara y la mantenibilidad es baja, por lo que no se recomienda.

  • Probable que sea señalado en revisiones de código
  • Confunde a los lectores más tarde
  • Ambiguo si es conversión o concatenación

Usar String.valueOf() explícitamente es más seguro.

7.3 Pasar double Directamente a BigDecimal

BigDecimal bd = new BigDecimal(0.1); // not recommended

Esto es peligroso porque usa un double que ya contiene un error de aproximación.

El enfoque correcto:

BigDecimal bd = new BigDecimal("0.1");

Para dinero y casos críticos de precisión, siempre créelo a partir de una cadena.

7.4 Escribir Código Asumiendo que No Habrá Excepciones

int i = Integer.parseInt(input);

En proyectos reales, la suposición de que la entrada siempre es válida rara vez se cumple.
Al manejar entradas externas, siempre incluya manejo de excepciones:

try {
    int i = Integer.parseInt(input);
} catch (NumberFormatException e) {
    // Error handling
}

7.5 Usar Valores Sin Ser Consciente de las Diferencias de Tipos

También es común usar tipos sin pensar en diferencias como int vs Integer, o double vs BigDecimal.

  • ¿Su objetivo es el cálculo?
  • ¿Su objetivo es la visualización?
  • ¿La precisión es crítica?

Elegir tipos basados en el propósito es la forma más rápida de prevenir errores.

8. Resumen

En Java, convertir entre números y cadenas se usa diariamente, pero también es un proceso donde pequeños errores pueden llevar a problemas mayores.

Lecciones clave de este artículo:

  • Para Number → String, String.valueOf() es el predeterminado
  • Para String → Number, elige entre parseXxx() y valueOf() según el tipo de retorno
  • Maneja la entrada externa asumiendo que pueden ocurrir excepciones
  • Usa BigDecimal para dinero y cálculos críticos de precisión
  • Evita patrones ambiguos como + ""

En lugar de memorizar métodos, es más importante elegir según el caso de uso y el tipo.
Con esta mentalidad, te atascarás mucho menos en el procesamiento fundamental de Java.

9. Preguntas frecuentes (FAQ)

Aquí resumimos puntos de tropiezo comunes para lectores que buscan “conversión de número a cadena en java” en formato de preguntas y respuestas.
Esta sección pretende llenar las lagunas que puedan quedar después de leer el texto principal.

Q1. ¿Cuál es la mejor manera única de convertir un número a una cadena en Java?

En general, el método más recomendado es String.valueOf().

Razones:

  • Consistente y fácil de entender
  • Funciona con tipos primitivos y clases wrapper
  • No lanza una excepción al pasar null
    String s = String.valueOf(100);
    

En proyectos reales, usarlo como predeterminado te ayuda a evitar errores.

Q2. ¿Cuál debo usar: parseInt o valueOf?

Elige según el tipo de retorno.

  • Integer.parseInt()int (primitivo)
  • Integer.valueOf()Integer (clase wrapper)

Si tu objetivo son cálculos, usa parseInt().
Si quieres almacenarlo en colecciones o tratarlo como un objeto, valueOf() es más adecuado.

Q3. ¿Hay una manera de verificar si una cadena es numérica antes de convertirla?

Un enfoque simple es usar una expresión regular.

boolean isNumber = input.matches("\\d+");

Sin embargo, este método tiene limitaciones:

  • Los decimales y negativos son difíciles de soportar
  • No puede garantizar una seguridad completa

Por lo tanto, en la práctica, es mejor asumir que try-catch sigue siendo necesario como medida de seguridad final.

Q4. ¿Por qué ocurre NumberFormatException durante la conversión numérica?

NumberFormatException ocurre cuando una cadena no puede interpretarse como un número.

Causas comunes:

  • Contiene caracteres no numéricos
  • Cadena vacía o null
  • Intentar convertir un decimal en un tipo entero
  • Contiene comas o símbolos

Al manejar entrada externa, siempre diseña bajo la suposición de que pueden ocurrir excepciones.

Q5. ¿Por qué no debo usar double para cálculos de dinero?

Porque double se almacena como una aproximación en binario, puede ocurrir un error de punto flotante.

double d = 0.1 + 0.2; // 0.30000000000000004

Para dinero, tasas y otros casos críticos de precisión, la elección correcta es usar BigDecimal creado desde una cadena.

BigDecimal bd = new BigDecimal("0.1");

Q6. ¿En qué debo tener cuidado al convertir valores de entrada de formularios a números?

Siempre ten en cuenta estos puntos:

  • Verifica cadenas null / vacías
  • Captura excepciones con try-catch
  • Define un comportamiento claro para casos de error

Trata la entrada del usuario como “potencialmente inválida” por defecto para prevenir errores.

Q7. ¿Qué pasa si quiero controlar el formato de visualización después de convertir a una cadena?

Mantén la conversión numérica y el formateo de visualización separados.

  • Conversión: String.valueOf() o BigDecimal
  • Formateo: usa DecimalFormat, etc.

Separar el procesamiento interno de la presentación mejora la mantenibilidad.