Saltar al contenido principal

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
  • indexOf devuelve la primera posición o -1 si no encuentra el texto.
  • contains responde si aparece una secuencia.
  • startsWith y endsWith comprueban 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 de equals.
  • Usar charAt(length()) como última posición.
  • Confundir el final excluido de substring.
  • Esperar que toUpperCase, strip o replace modifiquen el texto original.
  • No comprobar -1 antes de usar el resultado de indexOf como posición.
  • Suponer que split siempre 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.