String en profundidad
Un String representa texto. Ya lo usamos para nombres y respuestas; ahora aprenderemos a inspeccionarlo, compararlo y transformarlo para resolver tareas reales.
Longitud y posiciones
length() devuelve el número de caracteres:
String palabra = "Java";
System.out.println(palabra.length()); // 4
charAt(posicion) permite leer un carácter. Las posiciones empiezan en 0:
System.out.println(palabra.charAt(0)); // J
System.out.println(palabra.charAt(3)); // a
La última posición siempre es length() - 1. charAt(palabra.length()) queda fuera del texto y falla durante la ejecución.
Práctica inmediata
String lenguaje = "Java";
char primera = lenguaje.charAt(0);
char ultima = lenguaje.charAt(lenguaje.length() - 1);
System.out.println(primera + " - " + ultima);
La salida es J - a.
Extraer una parte con substring
String codigo = "JV1-05";
System.out.println(codigo.substring(0, 3)); // JV1
System.out.println(codigo.substring(4)); // 05
En substring(inicio, fin), se incluye inicio y se excluye fin. Con un solo argumento, el texto llega hasta el final.
Antes de extraer una parte variable, comprueba que las posiciones existen.
Buscar texto
String mensaje = "Aprender Java paso a paso";
System.out.println(mensaje.indexOf("Java")); // 9
System.out.println(mensaje.indexOf("Python")); // -1
System.out.println(mensaje.contains("paso")); // true
System.out.println(mensaje.startsWith("Aprender")); // true
System.out.println(mensaje.endsWith("paso")); // true
indexOfdevuelve la primera posición o-1si no encuentra el texto.containsresponde si aparece una secuencia.startsWithyendsWithcomprueban los extremos.
Mini reto: dominio sencillo
Comprueba si "alumna@skilly.es" contiene @ y termina en .es.
String correo = "alumna@skilly.es";
boolean formatoBasico = correo.contains("@") && correo.endsWith(".es");
System.out.println(formatoBasico); // true
Esto solo practica texto; no es una validación completa de correo.
Comparar contenido con equals
Para comparar el contenido de dos textos usamos equals:
String respuesta = "si";
if (respuesta.equals("si")) {
System.out.println("Continuamos");
}
No uses == para esta tarea. == no expresa una comparación fiable del contenido de dos String.
Si las mayúsculas no deben importar:
String respuesta = "SI";
System.out.println(respuesta.equalsIgnoreCase("si")); // true
Normalizar antes de comparar
strip() elimina espacios Unicode al principio y al final. Java 17 lo ofrece como opción moderna y más completa que trim():
String entrada = " Proyecto ";
String normalizada = entrada.strip().toLowerCase();
System.out.println(normalizada); // proyecto
toLowerCase() y toUpperCase() devuelven nuevas versiones en minúsculas o mayúsculas.
Los String son inmutables
Una operación no modifica el objeto de texto original:
String nombre = "Ana";
nombre.toUpperCase();
System.out.println(nombre); // Ana
Para conservar el resultado debemos asignarlo:
nombre = nombre.toUpperCase();
System.out.println(nombre); // ANA
La diferencia es observable: el primer código ignora el nuevo String; el segundo actualiza la variable para que apunte al resultado.
Reemplazar partes
String frase = "Java es difícil";
String revisada = frase.replace("difícil", "práctica");
System.out.println(revisada); // Java es práctica
replace también devuelve un texto nuevo. En esta unidad usamos reemplazos literales, sin expresiones regulares.
Separar datos con split
split divide un texto y devuelve un array. Los arrays se desarrollarán en la siguiente unidad; aquí basta con observar el resultado:
String linea = "Ana,8,Java";
String[] partes = linea.split(",");
System.out.println(partes[0]); // Ana
System.out.println(partes[1]); // 8
System.out.println(partes[2]); // Java
Elegimos una coma literal como separador sencillo. Casos avanzados y expresiones regulares quedan fuera.
Recorrer caracteres
Los bucles permiten analizar el texto posición a posición:
String palabra = "casa";
int vocales = 0;
for (int posicion = 0; posicion < palabra.length(); posicion++) {
char letra = palabra.charAt(posicion);
if (letra == 'a' || letra == 'e' || letra == 'i'
|| letra == 'o' || letra == 'u') {
vocales++;
}
}
System.out.println("Vocales: " + vocales); // 2
Un char se escribe con comillas simples; un String, con comillas dobles.
Programa completo: analizar una frase
import java.util.Scanner;
public class AnalizadorTexto {
public static void main(String[] args) {
Scanner entrada = new Scanner(System.in);
System.out.print("Escribe una frase: ");
String frase = entrada.nextLine().strip();
System.out.println("Caracteres: " + frase.length());
System.out.println("Mayúsculas: " + frase.toUpperCase());
System.out.println("Contiene Java: "
+ frase.toLowerCase().contains("java"));
System.out.println("Vocales: " + contarVocales(frase));
entrada.close();
}
public static int contarVocales(String texto) {
String normalizado = texto.toLowerCase();
int cantidad = 0;
for (int posicion = 0; posicion < normalizado.length(); posicion++) {
char letra = normalizado.charAt(posicion);
if (letra == 'a' || letra == 'e' || letra == 'i'
|| letra == 'o' || letra == 'u') {
cantidad++;
}
}
return cantidad;
}
}
Normalizamos una sola vez dentro del método y recorremos posiciones válidas desde 0 hasta length() - 1.
Errores habituales
- Comparar contenido con
==en vez deequals. - Usar
charAt(length())como última posición. - Confundir el final excluido de
substring. - Esperar que
toUpperCase,striporeplacemodifiquen el texto original. - No comprobar
-1antes de usar el resultado deindexOfcomo posición. - Suponer que
splitsiempre produce exactamente el número esperado de partes.
Ejercicio: nombre de usuario
Recibe un nombre y un apellido. Elimina espacios exteriores, convierte ambos a minúsculas y genera un usuario formado por la primera letra del nombre, un punto y el apellido. Informa también de si el apellido contiene la letra a.
Caso: " Ada " y " Lovelace " → a.lovelace; contiene a: true.
Solución razonada
public class GeneradorUsuario {
public static void main(String[] args) {
String nombre = " Ada ";
String apellido = " Lovelace ";
String nombreLimpio = nombre.strip().toLowerCase();
String apellidoLimpio = apellido.strip().toLowerCase();
String usuario = nombreLimpio.charAt(0) + "." + apellidoLimpio;
System.out.println(usuario);
System.out.println("Contiene a: " + apellidoLimpio.contains("a"));
}
}
Guardamos cada transformación porque los textos son inmutables. En la siguiente unidad estudiaremos el array que split nos ha permitido observar.