🧵 String en Java
🧠 ¿Qué es un String?
- Un
Stringrepresenta texto inmutable (no cambia después de crearse). - Internamente es una secuencia de char (unidades UTF-16).
- Java optimiza memoria con el String Pool: los literales
"hola"pueden compartirse. - Es una clase (
java.lang.String), no un tipo de datos primitivo.
String a = "hola"; // literal (va al String Pool)
String b = "hola"; // reutiliza el mismo literal
String c = new String("hola"); // FUERA del pool (no recomendado)
System.out.println(a == b); // true (misma referencia del pool)
System.out.println(a == c); // false (referencias distintas)
System.out.println(a.equals(c)); // true (mismo contenido)
Clave: Para comparar texto, usa equals (contenido), no == (referencia).
🧩 Inmutabilidad y por qué importa
- Inmutable ⇒ cada “cambio” en el String crea otro
String. - Ventajas: seguridad, hilos, cacheo en el pool, fácil de compartir.
- Inconveniente: concatenaciones repetidas pueden ser lentas y crear basura de objetos.
// 🔴 Ineficiente en bucles
String s = "";
for (int i = 0; i < 10_000; i++) {
s += i; // cada vuelta crea un String nuevo, no se modifica el String s, sino que se van creando nuevos
}
// ✅ Mejor con StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10_000; i++) {
sb.append(i);
}
String s2 = sb.toString();
🧭 Crear y obtener Strings
- Literales:
"Hola"(recomendado). - Conversión:
String.valueOf(123),Objects.toString(obj). - Formato:
String.format("Hola %s, tienes %d puntos", nombre, puntos). - Join:
String.join(", ", "rojo", "verde", "azul");. Concatena varios textos poniendo un separador entre cada uno, sin separador al principio ni al final.
String nombre = "Ada";
int puntos = 42;
String saludo = String.format("Hola %s, tienes %d puntos", nombre, puntos);
String lista = String.join(", ", List.of("rojo", "verde", "azul")); // "rojo, verde, azul"`
List<String> partes = List.of("2025", "10", "15");
String fecha = String.join("-", partes); // "2025-10-15"
🛠️ Métodos esenciales (con ejemplos)
📚 El operador concatenación +
La clase proporciona el operador + (concatenación) para unir dos o más String. El resultado de aplicar este operador es un nuevo String concatenación de los otros. Por ejemplo, si tenemos dos String b y c:
String b = "Ordenador";
String c = " Portátil";

La operación
b = b + c;
Crea un nuevo String que se incluye en el String Pool:

📏 Longitud y acceso. Índices
Cada uno de los caracteres que forman un String son del tipo primitivo char. Los caracteres de un string están numerados internamente con índices empezando desde el cero:

El primer carácter tiene índice 0 y el último tiene la longitud del string menos 1.
String s = "Hola";
s.length(); // 4
s.charAt(1); // 'o'
Para recorrer todos los caracteres que forman el String se utiliza un bucle for:
String major = "CSE";
for (int i = 0; i < major.length(); i++) {
char c = major.charAt(i);
System.out.println(c);
}
OUTPUT
C
S
E
🔍 Buscar y cortar
String t = "programar en Java";
t.indexOf("Java"); // 13
t.lastIndexOf("a"); // 16
t.contains("en "); // true
t.startsWith("pro"); // true
t.endsWith("Java"); // true
t.substring(0, 9); // "programar"
🔡 Mayúsculas / minúsculas / espacios
" Hola ".trim(); // "Hola" (quita espacios al principio y al final)
" Hola ".strip(); // "Hola" (quita espacios al principio y al final del texto, soporta espacios Unicode)
"\u00A0Hola\u00A0".trim(); // "\u00A0Hola\u00A0" (NO quita Non-Breaking Space)
"\u00A0Hola\u00A0".strip(); // "Hola" (sí lo quita)
"hola".toUpperCase(); // "HOLA"
"Hola".toLowerCase(); // "hola"
"".isEmpty(); // true
" ".isBlank(); // true (Java 11+)
🔁 Reemplazar y dividir
"12-34-56".replace("-", ":"); // "12:34:56"
"uno;dos;tres".split(";"); // ["uno", "dos", "tres"]
// ⚠️ split usa REGEX. Para texto literal, o escapamos o:
String[] partes = "a.b.c".split("\\."); // ["a","b","c"]
📐 Comparar
"Hola".equals("hola"); // false
"Hola".equalsIgnoreCase("hola"); // true
"abc".compareTo("abd"); // < 0 (orden lexicográfico)
🔁 Repetir
El método repeat(int count) devuelve un String formado por repetir esa cadena original count veces.
- Si count < 0 → IllegalArgumentException.
- count == 0 → "" (cadena vacía).
String texto = "*";
texto.repeat(2); //**
"ab".repeat(3); // "ababab"
"*".repeat(5); // "*****"
" hola".repeat(2); // " hola hola"
"\n- item".repeat(3); // "\n- item\n- item\n- item"
"🙂".repeat(4); // "🙂🙂🙂🙂"
" ".repeat(4) + "x"; // " x" (indentación)
🧵 Formateo y plantillas
String msg = String.format("PI: %.2f", Math.PI); // "PI: 3.14"
System.out.printf("Usuario: %s%n", "Max"); // Impresión formateada
🧪 Unicode, emojis y código seguro
- Un
chares una unidad UTF-16, no siempre un carácter visible. - Emojis y algunos símbolos usan pares sustitutos (surrogates).
- Para recorrer caracteres reales, usa code points:
String s = "A 😄 B";
s.length(); // 5 (porque 😄 usa 2 unidades UTF-16)
int realChars = s.codePointCount(0, s.length()); // 3
s.codePoints().forEach(cp -> {
System.out.println(Integer.toHexString(cp));
});
🧩 Qué es un code point
Un code point (en español, punto de código) es un número que identifica un carácter en Unicode. Cada carácter (letra, símbolo, emoji, etc.) tiene asignado un valor entero único, como una especie de DNI universal.
🧠 Ejemplos
| Carácter | Nombre | Código Unicode | Notación Java | Número,Valor decimal |
|---|---|---|---|---|
'A' |
Latin Capital Letter A | U+0041 | '\u0041' |
65 |
'ñ' |
Latin Small Letter Ñ | U+00F1 | '\u00F1' |
241 |
'漢' |
Han Character | U+6F22 | '\u6F22' |
28450 |
'😀' |
Grinning Face Emoji | U+1F600 | '\uD83D\uDE00' (par sustituto) |
128512 |
🔤 Clase Character
🧩 ¿Para qué sirve?
La clase Character permite analizar y transformar caracteres individuales según las reglas de Unicode.
Sirve para saber si algo es una letra, un dígito o un espacio; comprobar mayúsculas/minúsculas; convertir entre mayúsculas y minúsculas; validar identificadores; o trabajar correctamente con acentos, Ñ y otros alfabetos.
🧰 Métodos más usados
| Método | Descripción | Ejemplo |
|---|---|---|
🅰️ isLetter(cp) |
¿Es una letra? (categorías Unicode L*) | 'A', 'ñ', '漢' → ✅ |
🔠 isAlphabetic(cp) |
¿Es alfabético? (más amplio que isLetter) |
incluye números romanos tipo Ⅻ |
🔢 isDigit(cp) |
¿Es dígito? (0–9 y otros sistemas) | '3', '٣' → ✅ |
🔡 isLowerCase(cp) / 🔼 isUpperCase(cp) |
¿Minúscula o mayúscula? | 'a' → minúscula |
🔤 toLowerCase(cp) / toUpperCase(cp) / toTitleCase(cp) |
Convertir mayúsculas/minúsculas/título | 'ñ' → 'Ñ' |
🔣 isWhitespace(cp) |
¿Es espacio en blanco? (incluye tab, salto de línea, NBSP) | ' ' o '\n' → ✅ |
🔣 isLetterOrDigit(cp) |
¿Letra o dígito? | 'A', '5' → ✅ |
🧩 isJavaIdentifierStart(cp) / isJavaIdentifierPart(cp) |
¿Forma parte de un identificador Java? | _, 'x', '1' → ✅ |
💡 Tip Unicode: Recorre code points con String#codePoints() para que los métodos funcionen correctamente incluso con emojis u otros caracteres fuera del BMP.
⚡ Ejemplitos rápidos
Character.isLetter('ñ'); // true
Character.isAlphabetic('a'); // true
Character.isAlphabetic(0x216B); // Ⅻ (Roman Numeral Twelve)
Character.isDigit('2'); // true
Character.isWhitespace(' '); // true
Character.isUpperCase('U'); // true
Character.toLowerCase('U'); // false
🔡 Comprobar que un String contiene alguna letra mayúscula/minúscula o algún dígito
public static boolean tieneMayuscula(String texto) {
for (int i = 0; i < texto.length(); i++) {
if (Character.isUpperCase(texto.charAt(i))) {
return true;
}
}
return false;
}
public static boolean tieneMinuscula(String texto) {
for (int i = 0; i < texto.length(); i++) {
if (Character.isLowerCase(texto.charAt(i))) {
return true;
}
}
return false;
}
public static boolean tieneDigito(String texto) {
for (int i = 0; i < texto.length(); i++) {
if (Character.isDigit(texto.charAt(i))) {
return true;
}
}
return false;
}
⚠️ Otra opción con rangos de caracteres, pero ojo que tiene limitaciones de lenguaje
public static boolean tieneMayuscula(String texto) {
for (int i = 0; i < texto.length(); i++) {
if (texto.charAt(i) >= 'A' && texto.charAt(i) <= 'Z') {
return true;
}
}
return false;
}
public static boolean tieneMinuscula(String texto) {
for (int i = 0; i < texto.length(); i++) {
if (texto.charAt(i) >= 'a' && texto.charAt(i) <= 'z') {
return true;
}
}
return false;
}
🚦 String vs StringBuilder vs StringBuffer
| Opción | Característica | Cuándo usar |
|---|---|---|
String |
Inmutable, simple, seguro | Textos pequeños, concatenaciones puntuales, literales, claves de mapa |
StringBuilder |
Mutable, no sincronizado | Concatenaciones en bucle o construcción incremental de texto |
StringBuffer |
Mutable, sincronizado | Contextos multi‑hilo muy específicos (raro hoy) |
Regla práctica: si concatenas dentro de un bucle o en procesos largos, usa StringBuilder.
StringJoiner Pequeña utilidad para ir añadiendo elementos con separador, prefijo y sufijo.
StringJoiner j = new StringJoiner(", ", "[", "]"); j.add("rojo").add("verde").add("azul"); // "[rojo, verde, azul]"
🧯 Errores típicos (y cómo evitarlos)
- ❌ Usar
==en vez deequalspara comparar contenido. - ❌ Abusar de
+en bucles → usaStringBuilder. - ❌
splitsin escapar:".", "|", "?"son regex. Usa\\.oPattern.quote("."). - ❌ Confundir
replace(literal) conreplaceAll(regex). - ❌ Asumir que
length()es “caracteres visibles” (ojo con emojis). - ❌
nullvs""(cadena vacía) vs" "(en blanco). UsaisEmpty()/isBlank().
// ✅ Comparación segura null-safe
Objects.equals(cadena1, cadena2); // evita NullPointerException
🧭 ¿Cuándo usar Strings y cuándo no?
✅ Úsalos para…
- Mostrar mensajes, logs, etiquetas y entradas de usuario.
- Claves legibles (IDs, códigos) si no hay coste de rendimiento fuerte.
- Plantillas y formateo de salida.
⛔ Evítalos para…
- Grandes construcciones de texto en bucles → usa StringBuilder.
- Datos binarios → usa byte[].
- IDs que necesitan operaciones matemáticas → números/UUID (no String).
📝 Conversión de tipos (parseo y formateo)
// Número → String
String s1 = String.valueOf(1234); // "1234"
// String → Número
int n = Integer.parseInt("42"); // 42
double d = Double.parseDouble("3.14");
// Con formato localizado (ej.: separadores decimales)
NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMANY);
Number x = nf.parse("1.234,56"); // 1234.56 (como double)
🧱 Text Blocks (Java 15+)
Para textos multilínea legibles. Incluye saltos de línea y tabulaciones automáticamente. Las comillas triples de apertura deben ir solas en la línea. El cierre también (con posible indentación).
String html = """
<html>
<h1>Hola</h1>
</html>
""";
📌 Conclusión
Los String son fundamentales en Java. Entender inmutabilidad, pool, regex y StringBuilder te ahorra errores y mejora rendimiento. Usa esta hoja como guía rápida y practica los mini‑retos.