Clases en Java de utilidad

📅 Actualizado en febrero 2026 ✍️ Ángel López ⏱️ 24 min de lectura ✓ Nivel intermedio

Las clases de utilidad de Java son herramientas predefinidas que todo programador utiliza constantemente. Proporcionan métodos estáticos para realizar operaciones comunes — desde ordenar arrays y manipular cadenas de texto hasta cálculos matemáticos y conversión de tipos — sin necesidad de implementarlas desde cero.

En este artículo estudiaremos las clases de utilidad más importantes del JDK: comenzando por los arrays (la estructura de datos más básica), la clase Arrays con sus métodos de manipulación, String y StringBuilder para cadenas, Math para cálculos, las clases wrapper para envolver primitivos, y Collections para listas y mapas. Cada sección incluye código ejecutable y ejemplos prácticos.

📖 ¿Qué son las clases de utilidad?

Una clase de utilidad (también llamada helper class) es una clase que contiene solo métodos static y, por convención, un constructor privado para impedir su instanciación. No representan un «objeto» del mundo real, sino que agrupan funcionalidades relacionadas.

ClasePaqueteFunción principal
Arraysjava.utilOrdenar, buscar, copiar y comparar arrays
Stringjava.langRepresentar y manipular cadenas de texto inmutables
StringBuilderjava.langConstruir cadenas de forma eficiente (mutable)
Mathjava.langFunciones matemáticas (raíz, potencia, trigonometría...)
Integer, Double...java.langEnvolver primitivos como objetos (wrappers)
Collectionsjava.utilOrdenar, buscar y transformar colecciones

🗃️ Arrays (vectores)

Un array (vector) es una estructura que agrupa un conjunto de valores del mismo tipo bajo un mismo nombre. Se accede a cada elemento mediante un índice numérico que comienza en 0. Los arrays en Java son objetos con tamaño fijo, definido al crearlos.

📋 Declaración y creación

Java
// Dos formas de declarar (la segunda es preferida)
int vector1[];     // estilo C
int[] vector2;     // estilo Java (recomendado)

// Crear con tamaño fijo (30 elementos, inicializados a 0)
int[] numeros = new int[30];

// Crear e inicializar con valores entre llaves
int[] notas = {8, 9, 7, 10, 6, 8};

// Es equivalente a:
int[] notas2 = new int[6];
notas2[0] = 8;
notas2[1] = 9;
notas2[2] = 7;
notas2[3] = 10;
notas2[4] = 6;
notas2[5] = 8;

🔍 Acceso y recorrido

Java
int[] notas = {8, 9, 7, 10, 6, 8};

// Acceder por índice (0 a length-1)
System.out.println("Primera nota: " + notas[0]);   // 8
System.out.println("Última nota: " + notas[notas.length - 1]); // 8

// Recorrido con for clásico
System.out.println("Notas con for:");
for (int i = 0; i < notas.length; i++) {
    System.out.println("  Nota " + i + ": " + notas[i]);
}

// Recorrido con for-each (más limpio)
System.out.println("Notas con for-each:");
for (int nota : notas) {
    System.out.println("  → " + nota);
}

📊 Valores por defecto

Al crear un array con new, cada posición se inicializa automáticamente según el tipo:

TipoValor por defectoEjemplo
int, long, short, byte0new int[5] → {0, 0, 0, 0, 0}
float, double0.0new double[3] → {0.0, 0.0, 0.0}
char'\u0000' (nulo)Carácter nulo
booleanfalsenew boolean[2] → {false, false}
String y objetosnullnew String[3] → {null, null, null}

🔹 Argumentos de la línea de comandos

El parámetro String[] args del método main es un array que recibe los argumentos de la línea de comandos:

Java
public class Imprime {
    public static void main(String[] args) {
        for (String arg : args) {
            System.out.print(arg + " ");
        }
    }
}
// Ejecución: java Imprime hola que tal estas
// Salida:    hola que tal estas
💡
Recuerda: Los arrays son objetos, por lo que al pasarlos como argumento a un método se pasan por referencia. Los cambios realizados dentro del método afectan al array original.

🛠️ La clase java.util.Arrays

La clase Arrays proporciona métodos estáticos para las operaciones más habituales con arrays: ordenar, buscar, copiar, comparar y representar como cadena.

MétodoDescripciónComplejidad
sort(a)Ordena el array en orden ascendenteO(n log n)
binarySearch(a, key)Busca key en un array ya ordenadoO(log n)
copyOf(a, len)Copia los primeros len elementosO(n)
copyOfRange(a, from, to)Copia un rango del arrayO(n)
fill(a, val)Rellena todas las posiciones con valO(n)
equals(a, b)Compara si dos arrays tienen el mismo contenidoO(n)
toString(a)Devuelve una representación legibleO(n)
stream(a)Convierte el array en un StreamO(1)
Java
import java.util.Arrays;

public class DemoArrays {
    public static void main(String[] args) {
        int[] numeros = {42, 15, 8, 99, 23, 67, 4};

        // toString: representación legible
        System.out.println("Original: " + Arrays.toString(numeros));
        // [42, 15, 8, 99, 23, 67, 4]

        // sort: ordenar
        Arrays.sort(numeros);
        System.out.println("Ordenado: " + Arrays.toString(numeros));
        // [4, 8, 15, 23, 42, 67, 99]

        // binarySearch: buscar (requiere array ordenado)
        int pos = Arrays.binarySearch(numeros, 23);
        System.out.println("23 está en posición: " + pos);  // 3

        // copyOf: copiar
        int[] copia = Arrays.copyOf(numeros, 4);
        System.out.println("Copia: " + Arrays.toString(copia));
        // [4, 8, 15, 23]

        // fill: rellenar
        int[] relleno = new int[5];
        Arrays.fill(relleno, -1);
        System.out.println("Relleno: " + Arrays.toString(relleno));
        // [-1, -1, -1, -1, -1]

        // equals: comparar contenido
        int[] a = {1, 2, 3};
        int[] b = {1, 2, 3};
        System.out.println("¿Iguales? " + Arrays.equals(a, b));  // true
        System.out.println("¿Mismo objeto? " + (a == b));         // false

        // stream: programación funcional
        double media = Arrays.stream(numeros).average().orElse(0);
        System.out.printf("Media: %.1f%n", media);  // 36.9
    }
}

📝 La clase String

String es probablemente la clase más utilizada en Java. Representa una cadena de caracteres inmutable: una vez creada, su contenido no puede modificarse. Cada operación que aparentemente modifica un String en realidad crea un nuevo objeto.

🔑 Métodos esenciales

MétodoDescripciónEjemplo
length()Longitud de la cadena"Java".length() → 4
charAt(i)Carácter en la posición i"Java".charAt(0) → 'J'
substring(i, j)Subcadena desde i hasta j-1"Hola Mundo".substring(5, 10) → "Mundo"
indexOf(s)Posición de la primera ocurrencia"Java es genial".indexOf("es") → 5
contains(s)¿Contiene la subcadena?"Java 21".contains("21") → true
toUpperCase()Convierte a mayúsculas"java".toUpperCase() → "JAVA"
toLowerCase()Convierte a minúsculas"JAVA".toLowerCase() → "java"
trim()Elimina espacios al inicio y final" hola ".trim() → "hola"
replace(a, b)Reemplaza todas las ocurrencias"aaa".replace("a","b") → "bbb"
split(regex)Divide en un array por el separador"a,b,c".split(",") → ["a","b","c"]
equals(s)Compara contenido (NO usar ==)"Java".equals("Java") → true
Java
String texto = "  Programación en Java  ";

String limpio = texto.trim();                   // "Programación en Java"
String mayus  = limpio.toUpperCase();            // "PROGRAMACIÓN EN JAVA"
String[] palabras = limpio.split(" ");           // ["Programación", "en", "Java"]
boolean contiene = limpio.contains("Java");      // true
String reemplazo = limpio.replace("Java", "Python"); // "Programación en Python"

System.out.println("Palabras: " + palabras.length);  // 3
System.out.println("Contiene Java: " + contiene);     // true
System.out.println("Reemplazo: " + reemplazo);

⚡ StringBuilder y StringBuffer

Dado que String es inmutable, la concatenación repetida con + dentro de un bucle crea múltiples objetos temporales, lo que degrada el rendimiento. StringBuilder resuelve este problema: es una secuencia de caracteres mutable que permite añadir, insertar y modificar contenido sin crear objetos nuevos.

CaracterísticaStringStringBuilderStringBuffer
MutabilidadInmutableMutableMutable
SincronizadaNo (más rápida)Sí (thread-safe)
Uso recomendadoTextos que no cambianConstrucción iterativaEntornos multihilo
Java
// ❌ Ineficiente: crea un nuevo String en cada iteración
String resultado = "";
for (int i = 1; i <= 1000; i++) {
    resultado += i + ", ";  // 1000 objetos String temporales
}

// ✅ Eficiente: un solo objeto StringBuilder
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= 1000; i++) {
    sb.append(i);
    if (i < 1000) sb.append(", ");
}
String resultado2 = sb.toString();

// Otros métodos útiles
StringBuilder sb2 = new StringBuilder("Hola");
sb2.append(" Mundo");          // "Hola Mundo"
sb2.insert(5, " Buen");       // "Hola Buen Mundo"
sb2.replace(0, 4, "¡Hola");   // "¡Hola Buen Mundo"
sb2.reverse();                 // "odnuM neuB aloH¡"
System.out.println(sb2.length()); // 17
Regla práctica: Usa String para textos que no cambian, StringBuilder cuando construyas cadenas en bucles o condiciones, y StringBuffer solo si necesitas acceso concurrente desde múltiples hilos.

🔢 La clase Math

La clase java.lang.Math contiene métodos estáticos para operaciones matemáticas comunes. Es final (no puede heredarse) y tiene un constructor privado (no puede instanciarse).

MétodoDescripciónEjemplo
abs(x)Valor absolutoMath.abs(-7) → 7
max(a, b)Mayor de dos valoresMath.max(3, 9) → 9
min(a, b)Menor de dos valoresMath.min(3, 9) → 3
pow(base, exp)PotenciaMath.pow(2, 10) → 1024.0
sqrt(x)Raíz cuadradaMath.sqrt(144) → 12.0
round(x)Redondeo al entero más próximoMath.round(3.7) → 4
floor(x)Redondeo hacia abajoMath.floor(3.9) → 3.0
ceil(x)Redondeo hacia arribaMath.ceil(3.1) → 4.0
random()Aleatorio entre 0.0 y 1.0Math.random() → 0.73...
PIConstante πMath.PI → 3.14159...
EConstante eMath.E → 2.71828...
Java
// Área de un círculo
double radio = 5.0;
double area = Math.PI * Math.pow(radio, 2);
System.out.printf("Área: %.2f%n", area);  // 78.54

// Distancia entre dos puntos (teorema de Pitágoras)
double x1 = 3, y1 = 4, x2 = 7, y2 = 1;
double distancia = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
System.out.printf("Distancia: %.2f%n", distancia);  // 5.00

// Número aleatorio entre 1 y 100
int aleatorio = (int) (Math.random() * 100) + 1;
System.out.println("Aleatorio: " + aleatorio);

📦 Clases wrapper (envoltorio)

Las colecciones genéricas de Java (ArrayList, HashMap) solo aceptan objetos, no tipos primitivos. Las clases wrapper envuelven cada primitivo en un objeto, y Java realiza la conversión automáticamente mediante autoboxing y unboxing.

PrimitivoWrapperMétodo de conversiónConstantes útiles
byteByteByte.parseByte("42")MIN_VALUE, MAX_VALUE
shortShortShort.parseShort("42")MIN_VALUE, MAX_VALUE
intIntegerInteger.parseInt("42")MIN_VALUE, MAX_VALUE
longLongLong.parseLong("42")MIN_VALUE, MAX_VALUE
floatFloatFloat.parseFloat("3.14")NaN, POSITIVE_INFINITY
doubleDoubleDouble.parseDouble("3.14")NaN, POSITIVE_INFINITY
charCharacterCharacter.isDigit('5')isLetter(), isUpperCase()
booleanBooleanBoolean.parseBoolean("true")TRUE, FALSE
Java
// Autoboxing: primitivo → objeto (automático)
Integer numObj = 42;           // equivale a Integer.valueOf(42)
Double piObj = 3.14;           // equivale a Double.valueOf(3.14)

// Unboxing: objeto → primitivo (automático)
int num = numObj;              // equivale a numObj.intValue()
double pi = piObj;

// Conversión String → primitivo
int edad = Integer.parseInt("25");
double precio = Double.parseDouble("19.99");

// Conversión primitivo → String
String edadStr = Integer.toString(25);       // "25"
String precioStr = String.valueOf(19.99);    // "19.99"

// Constantes útiles
System.out.println("int máximo: " + Integer.MAX_VALUE);  // 2147483647
System.out.println("int mínimo: " + Integer.MIN_VALUE);  // -2147483648

// Métodos de Character
System.out.println(Character.isDigit('5'));      // true
System.out.println(Character.isLetter('A'));     // true
System.out.println(Character.toUpperCase('a'));  // 'A'
⚠️
Cuidado con null: Los wrappers pueden ser null, a diferencia de los primitivos. Si haces unboxing de un wrapper null, se lanza NullPointerException: Integer x = null; int y = x; → ¡Error!

🗂️ La clase Collections

La clase java.util.Collections (con «s» final, no confundir con la interfaz Collection) proporciona métodos estáticos para manipular colecciones como List, Set y Map. Es el equivalente de la clase Arrays pero orientado al framework de colecciones, y resulta imprescindible en cualquier proyecto Java de tamaño medio o grande.

MétodoDescripciónEjemplo de uso
sort(list)Ordena la lista en orden naturalOrdenar nombres alfabéticamente
reverse(list)Invierte el orden de los elementosMostrar ranking de mayor a menor
shuffle(list)Mezcla aleatoriamenteBarajar cartas, preguntas de examen
min(col) / max(col)Devuelve el menor / mayor elementoEncontrar el precio más bajo
frequency(col, obj)Cuenta cuántas veces aparece un elementoContar votos de un candidato
unmodifiableList(list)Devuelve una vista de solo lecturaProteger datos de configuración
Java
import java.util.*;

public class DemoCollections {
    public static void main(String[] args) {
        List<String> ciudades = new ArrayList<>(
            Arrays.asList("Madrid", "Barcelona", "Sevilla", "Valencia", "Bilbao")
        );

        // sort: ordenar alfabéticamente
        Collections.sort(ciudades);
        System.out.println("Ordenadas: " + ciudades);
        // [Barcelona, Bilbao, Madrid, Sevilla, Valencia]

        // reverse: invertir el orden
        Collections.reverse(ciudades);
        System.out.println("Invertidas: " + ciudades);
        // [Valencia, Sevilla, Madrid, Bilbao, Barcelona]

        // shuffle: mezclar aleatoriamente
        Collections.shuffle(ciudades);
        System.out.println("Mezcladas: " + ciudades);

        // min y max
        System.out.println("Mín: " + Collections.min(ciudades));
        System.out.println("Máx: " + Collections.max(ciudades));

        // frequency: contar ocurrencias
        List<Integer> nums = Arrays.asList(1, 3, 5, 3, 7, 3, 9);
        System.out.println("Veces que aparece 3: " + Collections.frequency(nums, 3));  // 3

        // unmodifiableList: lista de solo lectura
        List<String> soloLectura = Collections.unmodifiableList(ciudades);
        // soloLectura.add("Málaga");  // ¡UnsupportedOperationException!
    }
}

🏗️ Ejemplo integrador

El siguiente programa combina todas las clases de utilidad estudiadas para procesar un registro de calificaciones de estudiantes: usa arrays, Arrays, String, StringBuilder, Math e Integer en un único flujo coherente.

GestorCalificaciones.java
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class GestorCalificaciones {

    public static void main(String[] args) {
        // Datos de entrada como cadenas (simula lectura de archivo)
        String datos = "Ana:8,9,7;Luis:6,5,8;María:10,9,10;Pedro:4,6,3";

        // Procesar cada estudiante
        String[] estudiantes = datos.split(";");
        List<String> resultados = new ArrayList<>();
        StringBuilder informe = new StringBuilder();
        informe.append("╔══════════════════════════════════════════╗\n");
        informe.append("║     INFORME DE CALIFICACIONES            ║\n");
        informe.append("╠══════════════════════════════════════════╣\n");

        double mediaGlobal = 0;
        int totalEstudiantes = estudiantes.length;

        for (String est : estudiantes) {
            // Separar nombre y notas
            String nombre = est.split(":")[0].trim();
            String[] notasStr = est.split(":")[1].split(",");

            // Convertir String[] a int[] usando wrapper Integer
            int[] notas = new int[notasStr.length];
            for (int i = 0; i < notasStr.length; i++) {
                notas[i] = Integer.parseInt(notasStr[i].trim());
            }

            // Cálculos con Arrays y Math
            double media = Arrays.stream(notas).average().orElse(0);
            int maxNota = Arrays.stream(notas).max().orElse(0);
            int minNota = Arrays.stream(notas).min().orElse(0);
            String estado = media >= 5 ? "APROBADO ✅" : "SUSPENDIDO ❌";

            // Construir línea del informe con StringBuilder
            informe.append(String.format("║ %-8s | Notas: %-10s | Media: %.1f %s%n",
                nombre, Arrays.toString(notas), media, estado));

            resultados.add(nombre + ": " + String.format("%.1f", media));
            mediaGlobal += media;
        }

        informe.append("╠══════════════════════════════════════════╣\n");
        informe.append(String.format("║ Media global: %.2f%n", mediaGlobal / totalEstudiantes));
        informe.append("╚══════════════════════════════════════════╝");

        System.out.println(informe);

        // Ordenar resultados con Collections
        Collections.sort(resultados);
        System.out.println("\nRanking alfabético: " + resultados);
    }
}

❌ Errores frecuentes

🔹 Error 1: comparar Strings con ==

Java
String a = new String("Java");
String b = new String("Java");

// ❌ Compara referencias (direcciones de memoria), NO contenido
System.out.println(a == b);          // false

// ✅ Compara contenido
System.out.println(a.equals(b));     // true

🔹 Error 2: ArrayIndexOutOfBoundsException

Java
int[] nums = {10, 20, 30};

// ❌ Índice 3 no existe (válidos: 0, 1, 2)
System.out.println(nums[3]);  // 💥 ArrayIndexOutOfBoundsException

// ✅ Usar length para evitarlo
for (int i = 0; i < nums.length; i++) {  // length = 3, itera 0, 1, 2
    System.out.println(nums[i]);
}

🔹 Error 3: binarySearch en array no ordenado

Java
int[] datos = {42, 15, 8, 99};

// ❌ binarySearch requiere array ORDENADO
int pos = Arrays.binarySearch(datos, 15);  // Resultado impredecible

// ✅ Ordenar primero
Arrays.sort(datos);                         // [8, 15, 42, 99]
int pos2 = Arrays.binarySearch(datos, 15);  // 1 (correcto)

📝 Ejercicios prácticos

Ejercicio 1: Estadísticas de un array

Dado el array {45, 78, 12, 95, 33, 67, 88, 21}, escribe un programa que calcule: la suma, la media, el máximo, el mínimo y cuántos elementos superan la media. Usa Arrays y Math.

Ejercicio 2: Analizador de texto

Escribe un programa que reciba una frase y muestre: número de caracteres, número de palabras, número de vocales, la frase invertida y la frase con cada palabra capitalizada.

Ejercicio 3: Conversor de temperaturas

Usando Math y String.format, escribe un programa que genere una tabla de conversión de Celsius a Fahrenheit y Kelvin para las temperaturas de 0 a 100 de 10 en 10. Fórmulas: F = C × 9/5 + 32 y K = C + 273.15.

❓ Preguntas frecuentes sobre Clases en Java de utilidad

Las dudas más comunes respondidas de forma clara y directa.

Las clases de utilidad son clases que proporcionan métodos estáticos para realizar operaciones comunes sin necesidad de crear instancias. Los ejemplos más importantes son java.util.Arrays (para manipular arrays), java.lang.Math (para operaciones matemáticas), java.util.Collections (para manipular colecciones) y las clases wrapper como Integer o Double. Simplifican el código al ofrecer funcionalidades predefinidas y optimizadas.
Un array tiene tamaño fijo definido al crearlo y puede almacenar tanto tipos primitivos como objetos. Un ArrayList es dinámico (crece automáticamente), pero solo almacena objetos (usa autoboxing para primitivos). Los arrays son más rápidos y usan menos memoria, mientras que ArrayList ofrece métodos como add(), remove() y contains() que simplifican la gestión de datos.
Porque String es inmutable: cada concatenación con + crea un nuevo objeto en memoria. En un bucle que concatena muchas veces, esto genera miles de objetos temporales y degrada el rendimiento. StringBuilder modifica la misma instancia internamente sin crear objetos nuevos, siendo mucho más eficiente para la construcción iterativa de cadenas.
Las clases wrapper (envoltorio) son clases que representan tipos primitivos como objetos: Integer para int, Double para double, Boolean para boolean, etc. Son necesarias porque las colecciones genéricas (ArrayList, HashMap) solo aceptan objetos, no primitivos. Además proporcionan métodos útiles como parseInt(), compareTo() y constantes como MAX_VALUE. Java realiza autoboxing y unboxing automáticamente entre primitivos y wrappers.
La clase Arrays ofrece métodos estáticos esenciales: sort() para ordenar, binarySearch() para buscar eficientemente en arrays ordenados, copyOf() y copyOfRange() para copiar, fill() para rellenar con un valor, equals() para comparar contenido, toString() para representación legible, y stream() para convertir a Stream y usar programación funcional.
Valora este artículo

💬 Foro de discusión

¿Tienes dudas sobre Clases en Java de utilidad? Comparte tu pregunta con la comunidad.

¿Tienes cuenta? o comenta como invitado ↓

Todavía no hay mensajes. ¡Sé el primero en participar!