Saltar al contenido
cadenas.java · devschool

String y StringBuilder en Java

Lección 7 de 26 · 10 min de lectura · Actualizado el

En esta lección
  1. Qué es un String
  2. Los strings son inmutables
  3. Métodos de String más usados
  4. Comparar strings
  5. StringBuilder: texto que se modifica
  6. Dar formato: printf y String.format
  7. Text blocks: texto de varias líneas
  8. La clase Character
  9. Errores frecuentes
  10. Resumen

Casi todos los programas trabajan con texto: nombres de clientes, correos, contraseñas, líneas de un fichero. En Java el texto se guarda en objetos de la clase String, que trae decenas de métodos para buscar, recortar, transformar y comparar. En esta lección verás los métodos que usarás a diario, por qué un String no se puede modificar, cuándo necesitas StringBuilder y cómo dar formato a la salida con printf.

Qué es un String

Un String es una secuencia de caracteres (char). Se escribe entre comillas dobles y cada carácter ocupa una posición, empezando en 0, igual que en los arrays:

 D  e  v  S  c  h  o  o  l
 0  1  2  3  4  5  6  7  8
String escuela = "DevSchool";
System.out.println(escuela.length());   // 9
System.out.println(escuela.charAt(0));  // D
System.out.println(escuela.charAt(8));  // l
  • length() devuelve el número de caracteres. En los strings lleva paréntesis (es un método); en los arrays, length va sin ellos.
  • charAt(i) devuelve el carácter de la posición i. La última posición es length() - 1; si te pasas, obtienes StringIndexOutOfBoundsException.

Los strings son inmutables

Un objeto String no se puede cambiar una vez creado. Todos los métodos que parecen modificarlo en realidad devuelven un String nuevo y dejan el original intacto:

String nombre = "lucía";
nombre.toUpperCase();              // crea "LUCÍA", pero nadie lo guarda
System.out.println(nombre);        // lucía

nombre = nombre.toUpperCase();     // guardamos el nuevo en la variable
System.out.println(nombre);        // LUCÍA

Es un error muy común llamar a trim() o replace() y olvidarse de guardar el resultado. ¿Por qué Java lo hace así? Porque un objeto inmutable se puede compartir sin miedo: si dos variables apuntan al mismo "Hola", ninguna puede estropeárselo a la otra. Además permite que Java reutilice los literales iguales para ahorrar memoria.

Métodos de String más usados

Buscar

String correo = "marta.ruiz@devschool.es";

System.out.println(correo.indexOf('@'));        // 10
System.out.println(correo.indexOf("school"));   // 14
System.out.println(correo.indexOf("gmail"));    // -1
System.out.println(correo.lastIndexOf('.'));    // 20
System.out.println(correo.contains("@"));       // true
System.out.println(correo.startsWith("marta")); // true
System.out.println(correo.endsWith(".es"));     // true

indexOf devuelve la primera posición donde aparece lo que buscas, o -1 si no está. lastIndexOf busca desde el final.

Extraer: substring

substring(inicio, fin) devuelve el trozo que va desde inicio incluido hasta fin excluido. Con un solo argumento, llega hasta el final:

String correo = "marta.ruiz@devschool.es";
int arroba = correo.indexOf('@');

String usuario = correo.substring(0, arroba);
String dominio = correo.substring(arroba + 1);
System.out.println(usuario); // marta.ruiz
System.out.println(dominio); // devschool.es

Que el final sea excluido tiene una ventaja: fin - inicio es justo la longitud del trozo. "DevSchool".substring(0, 3) son 3 caracteres: Dev.

Transformar

String texto = "  Hola Mundo  ";

System.out.println(texto.toUpperCase());           //   HOLA MUNDO  
System.out.println(texto.toLowerCase());           //   hola mundo  
System.out.println("[" + texto.trim() + "]");      // [Hola Mundo]
System.out.println("[" + texto.strip() + "]");     // [Hola Mundo]
System.out.println(texto.trim().replace('o', '0')); // H0la Mund0
System.out.println("ja".repeat(3));                // jajaja
  • trim() y strip() quitan los espacios del principio y del final. strip() es la versión moderna (Java 11) y también reconoce los espacios Unicode especiales; úsala en código nuevo. Existen stripLeading() y stripTrailing() para un solo lado.
  • replace sustituye todas las apariciones, de un carácter o de un texto: "a-b-c".replace("-", ", ") da a, b, c.

Dividir y unir

split parte un texto por un separador y devuelve un array. String.join hace lo contrario:

String linea = "Ana;20;Madrid";
String[] partes = linea.split(";");
System.out.println(partes.length); // 3
System.out.println(partes[0]);     // Ana
System.out.println(partes[2]);     // Madrid

String unido = String.join(" | ", partes);
System.out.println(unido);         // Ana | 20 | Madrid

Es la base para leer ficheros CSV, que verás en ficheros.

Cuidado: el argumento de split es una expresión regular. Para partir por un punto no vale split("."), porque el punto significa “cualquier carácter”; escribe split("\\."). Lo mismo con |: split("\\|").

Comprobar si está vacío

System.out.println("".isEmpty());     // true
System.out.println("   ".isEmpty());  // false
System.out.println("   ".isBlank());  // true

isEmpty() solo es true si la longitud es 0. isBlank() (Java 11) también da true si solo hay espacios, que es lo que normalmente quieres al validar un formulario.

Comparar strings

Como viste en operadores, un String es un objeto y == compara si son el mismo objeto, no si tienen el mismo texto:

String a = "java";
String b = new String("java");
String c = "JAVA";

System.out.println(a == b);               // false
System.out.println(a.equals(b));          // true
System.out.println(a.equals(c));          // false
System.out.println(a.equalsIgnoreCase(c)); // true
FormaQué compara¿Cuándo usarla?
a == bSi son el mismo objetoCasi nunca con String
a.equals(b)Mismo texto, exactoSiempre para comparar contenido
a.equalsIgnoreCase(b)Mismo texto sin mirar mayúsculasComandos, respuestas del usuario

Si una variable puede ser null, escribe primero el literal: "salir".equals(comando). Así, si comando es null, obtienes false en lugar de un NullPointerException.

Ordenar: compareTo

compareTo compara alfabéticamente y devuelve un número: negativo si el primero va antes, 0 si son iguales y positivo si va después.

System.out.println("ana".compareTo("luis") < 0);  // true: ana va antes
System.out.println("pera".compareTo("pera"));     // 0
System.out.println("Zoe".compareTo("ana") < 0);   // true

El último sorprende: compara por código Unicode, y todas las mayúsculas van antes que las minúsculas. Para ignorar mayúsculas existe compareToIgnoreCase.

StringBuilder: texto que se modifica

Como los String son inmutables, cada + en un bucle crea un objeto nuevo y copia todo el texto anterior. Con pocas vueltas no se nota, pero con miles el programa se vuelve lento y gasta mucha memoria:

String resultado = "";
for (int i = 0; i < 5; i++) {
    resultado += i + ","; // crea un String nuevo en cada vuelta
}
System.out.println(resultado); // 0,1,2,3,4,

StringBuilder es un texto modificable: va añadiendo sobre el mismo objeto, sin copias.

StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5; i++) {
    sb.append(i).append(",");
}
sb.setLength(sb.length() - 1);  // quita la última coma
String resultado = sb.toString();
System.out.println(resultado);  // 0,1,2,3,4

Sus métodos principales:

StringBuilder sb = new StringBuilder("Java");
sb.append(" 21");            // añade al final
System.out.println(sb);      // Java 21
sb.insert(0, "Curso de ");   // inserta en una posición
System.out.println(sb);      // Curso de Java 21
sb.reverse();                // le da la vuelta
System.out.println(sb);      // 12 avaJ ed osruC
System.out.println(sb.length()); // 16

A diferencia de String, estos métodos sí modifican el objeto. Cuando termines, conviértelo con toString().

Un uso típico: comprobar si una palabra es un palíndromo.

String palabra = "reconocer";
String alReves = new StringBuilder(palabra).reverse().toString();
System.out.println(palabra.equals(alReves)); // true

Consejo: para unir unas pocas piezas en una línea, usa + sin miedo; el compilador lo optimiza. Usa StringBuilder cuando construyas un texto dentro de un bucle.

Dar formato: printf y String.format

Concatenar con + se complica cuando quieres alinear columnas o limitar decimales. printf usa una plantilla con marcadores que se sustituyen por los valores en orden:

String producto = "Teclado";
int unidades = 3;
double precio = 24.5;

System.out.printf("%s: %d uds. a %.2f euros%n", producto, unidades, precio);
Teclado: 3 uds. a 24.50 euros
MarcadorTipoEjemploResultado
%sTexto (o cualquier objeto)"%s", "Ana"Ana
%dEntero"%d", 4242
%fDecimal (6 decimales)"%f", 3.53.500000
%.2fDecimal con 2 decimales (redondea)"%.2f", 3.4563.46
%5dEntero en 5 huecos, a la derecha"%5d", 42 42
%-8sTexto en 8 huecos, a la izquierda"%-8s", "Ana"Ana
%nSalto de línea

String.format funciona igual, pero devuelve el texto en lugar de mostrarlo:

String ticket = String.format("%-10s%6.2f", "Pan", 1.2);
System.out.println("[" + ticket + "]"); // [Pan         1.20]

Con anchos fijos puedes alinear una tabla:

String[] productos = {"Pan", "Leche", "Aceite"};
double[] precios = {1.2, 0.95, 8.75};
for (int i = 0; i < productos.length; i++) {
    System.out.printf("%-8s%6.2f%n", productos[i], precios[i]);
}
Pan       1.20
Leche     0.95
Aceite    8.75

Cuidado: printf usa el idioma del sistema. En un ordenador en español, %.2f muestra coma decimal (24,50). Si necesitas siempre punto, usa String.format(Locale.US, ...).

Text blocks: texto de varias líneas

Desde Java 15 puedes escribir textos largos entre triples comillas, respetando los saltos de línea y sin escapar las comillas:

String json = """
    {
      "nombre": "Ana",
      "curso": "Java"
    }
    """;
System.out.print(json);
{
  "nombre": "Ana",
  "curso": "Java"
}

Java elimina la sangría común a todas las líneas, tomando como referencia la posición de las comillas de cierre. Son ideales para JSON, HTML o consultas SQL, como las que escribirás en JDBC.

La clase Character

Para analizar un texto carácter a carácter, la clase Character tiene métodos que clasifican un char:

String clave = "Java2026!";
int letras = 0, digitos = 0, otros = 0;

for (int i = 0; i < clave.length(); i++) {
    char c = clave.charAt(i);
    if (Character.isLetter(c)) {
        letras++;
    } else if (Character.isDigit(c)) {
        digitos++;
    } else {
        otros++;
    }
}
System.out.println(letras + " letras, " + digitos + " dígitos, " + otros + " otros");
// 4 letras, 4 dígitos, 1 otros

Otros útiles: Character.isUpperCase(c), Character.isLowerCase(c), Character.isWhitespace(c), Character.toUpperCase(c) y Character.isLetterOrDigit(c).

También puedes recorrer un texto con for-each convirtiéndolo antes en array: for (char c : clave.toCharArray()).

Errores frecuentes

  • No guardar el resultado: texto.trim(); no cambia texto. Escribe texto = texto.trim();.
  • Comparar con ==: usa equals.
  • Confundir length y length(): arrays sin paréntesis, strings con ellos.
  • Salirse del texto: charAt(texto.length()) lanza StringIndexOutOfBoundsException.
  • split("."): el punto es especial; usa split("\\.").
  • Concatenar en bucles largos: usa StringBuilder.
  • Llamar a un método sobre null: String s = null; s.length(); lanza NullPointerException.

Resumen

Necesito…Método
Longitud / un carácterlength(), charAt(i)
BuscarindexOf, lastIndexOf, contains, startsWith, endsWith
Extraersubstring(inicio, fin)
TransformartoUpperCase, toLowerCase, strip, trim, replace, repeat
Dividir / unirsplit, String.join
Comprobar vacíoisEmpty, isBlank
Compararequals, equalsIgnoreCase, compareTo
Construir en buclesStringBuilder: append, insert, reverse, toString
Formatearprintf, String.format

Recuerda que los String son inmutables: sus métodos devuelven textos nuevos. Para convertir un texto en número ("25" en 25) sigue con Math, conversiones y clases envoltorio.

Pon a prueba lo que has aprendido

[Java] ¿Qué imprime este código?
String saludo = "  hola  ";
saludo.strip();
saludo.toUpperCase();
System.out.println("[" + saludo + "]");

[Java] ¿Qué imprime este código?
String archivo = "informe_final.pdf";
int punto = archivo.indexOf('.');
System.out.println(archivo.substring(punto + 1) + " " + archivo.substring(0, 7));

[Java] ¿Por qué se recomienda StringBuilder para construir un texto dentro de un bucle largo?

[Java] ¿Qué imprime este código?
String fecha = "30.09.2026";
String[] partes = fecha.split(".");
System.out.println(partes.length);

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.