Arrays en Java

📅 Actualizado en febrero 2026 ✍️ Ángel López ⏱️ 22 min de lectura ✓ Nivel principiante ★ ★ ★ ★ ★ (5/5)

📦 ¿Qué es un array en Java?

Un array (también llamado arreglo o vector) es una estructura de datos que almacena una colección de elementos del mismo tipo en posiciones consecutivas de memoria. Cada elemento se identifica por un índice numérico que comienza en 0 y llega hasta longitud - 1.

Los arrays son una de las estructuras más fundamentales de cualquier lenguaje de programación. En Java, un array es un objeto: se crea en el heap, hereda de java.lang.Object y tiene la propiedad length. Esta naturaleza de objeto implica que las variables de array almacenan referencias, no los datos directamente.

💡
Concepto clave: En Java, los arrays tienen tamaño fijo. Una vez creado un array de 10 posiciones, no se puede ampliar ni reducir. Si necesitas una estructura de tamaño variable, debes usar una colección como ArrayList.

Las características principales de los arrays en Java son:

Tipado estricto: todos los elementos deben ser del mismo tipo (o subtipos compatibles).
Tamaño fijo: se define al crearlo y no cambia.
Indexación desde cero: el primer elemento es [0] y el último [length - 1].
Acceso directo: acceder a cualquier posición es O(1), lo que hace a los arrays extremadamente eficientes para lectura.
Inicialización automática: Java asigna valores por defecto a cada posición.

Tipo del array Valor por defecto Ejemplo
int[], long[], short[], byte[] 0 int[] nums = new int[5]; // {0, 0, 0, 0, 0}
double[], float[] 0.0 double[] ds = new double[3]; // {0.0, 0.0, 0.0}
boolean[] false boolean[] bs = new boolean[2]; // {false, false}
char[] '\u0000' char[] cs = new char[3]; // {'\u0000', '\u0000', '\u0000'}
String[], objetos null String[] ss = new String[4]; // {null, null, null, null}

📝 Declaración e inicialización de arrays

En Java existen tres formas principales de declarar y crear un array. Es fundamental entender las diferencias entre declaración, creación e inicialización, ya que son pasos distintos que pueden realizarse juntos o por separado.

🔹 Forma 1: Declaración y creación con new

Se declara la variable y se reserva memoria para un número fijo de posiciones. Los elementos se inicializan con los valores por defecto del tipo.

Java
// Declarar y crear un array de 5 enteros
int[] numeros = new int[5];

// Equivalente (estilo C, menos idiomático en Java):
int numeros2[] = new int[5];

// Arrays de otros tipos
double[] precios = new double[100];
String[] nombres = new String[10];
boolean[] activos = new boolean[50];
Buena práctica: En Java se prefiere la sintaxis int[] numeros sobre int numeros[]. La primera deja claro que el tipo es «array de int», mientras que la segunda es una herencia de C que puede generar confusión con declaraciones múltiples.

🔹 Forma 2: Inicialización directa con llaves

Se declara, crea e inicializa el array en una sola sentencia. Java infiere el tamaño a partir del número de valores proporcionados.

Java
// Array de 4 enteros con valores específicos
int[] edades = {25, 30, 18, 42};

// Array de Strings
String[] colores = {"rojo", "verde", "azul"};

// Array de doubles
double[] notas = {8.5, 9.0, 7.3, 6.8, 10.0};

🔹 Forma 3: Creación anónima con new y valores

Útil cuando se necesita pasar un array como argumento a un método sin declarar una variable previa, o cuando se reasigna un array existente.

Java
// Reasignar un array existente
int[] datos;
datos = new int[]{10, 20, 30};

// Pasar array como argumento
procesarDatos(new int[]{1, 2, 3, 4});

// NOTA: esto NO compila
// int[] x; x = {1, 2, 3}; ← Error: la forma con llaves solo funciona en la declaración
⚠️
Error frecuente: Intentar usar la sintaxis {1, 2, 3} fuera de la declaración genera un error de compilación. Fuera de la línea de declaración, debes usar new int[]{1, 2, 3}.

🔑 Acceso a elementos y propiedad length

Cada elemento de un array se accede mediante su índice entre corchetes. El índice es un número entero que empieza en 0 (primer elemento) y llega hasta length - 1 (último elemento). La propiedad length (sin paréntesis, ya que no es un método) devuelve el número total de posiciones del array.

Java
String[] ciudades = {"Madrid", "Barcelona", "Sevilla", "Valencia"};

// Leer elementos
System.out.println(ciudades[0]);  // Madrid (primer elemento)
System.out.println(ciudades[3]);  // Valencia (último elemento)

// Modificar un elemento
ciudades[1] = "Bilbao";  // Barcelona → Bilbao

// Propiedad length
System.out.println(ciudades.length);  // 4

// Último elemento (patrón idiomático)
String ultima = ciudades[ciudades.length - 1];  // Valencia
💡
Dato importante: length es un campo público (atributo) del array, no un método. Por eso se escribe array.length sin paréntesis. Esto es diferente de String.length(), que sí es un método.

🔄 Recorrido con bucle for clásico

El bucle for clásico es la forma más flexible de recorrer un array, ya que proporciona acceso directo al índice. Esto permite leer, modificar y conocer la posición exacta de cada elemento.

Java
int[] temperaturas = {22, 28, 19, 31, 25, 17, 30};

// Recorrido completo
for (int i = 0; i < temperaturas.length; i++) {
    System.out.println("Día " + (i + 1) + ": " + temperaturas[i] + "°C");
}

// Buscar el máximo
int max = temperaturas[0];
int posMax = 0;
for (int i = 1; i < temperaturas.length; i++) {
    if (temperaturas[i] > max) {
        max = temperaturas[i];
        posMax = i;
    }
}
System.out.println("Máxima: " + max + "°C el día " + (posMax + 1));

▶️ Recorrido inverso

Para recorrer un array desde el último elemento hasta el primero, se inicia el índice en length - 1 y se decrementa:

Java
String[] palabras = {"Hola", "mundo", "Java"};

// Recorrido inverso
for (int i = palabras.length - 1; i >= 0; i--) {
    System.out.println(palabras[i]);
}
// Salida: Java, mundo, Hola

🔁 Recorrido con for-each (enhanced for)

Desde Java 5, el bucle for-each simplifica la lectura de arrays cuando no necesitas el índice. La sintaxis es más limpia y menos propensa a errores de límites.

Java
double[] precios = {19.99, 5.50, 12.75, 8.30, 45.00};

// Sintaxis: for (tipo variable : array)
double total = 0;
for (double precio : precios) {
    total += precio;
}
System.out.println("Total: " + total);  // Total: 91.54

// Ejemplo con Strings
String[] frutas = {"Manzana", "Plátano", "Naranja"};
for (String fruta : frutas) {
    System.out.println("Fruta: " + fruta);
}
Característica Bucle for clásico Bucle for-each
Acceso al índice No
Modificar elementos Sí (array[i] = valor) No (la variable es una copia)
Recorrer en orden inverso No
Legibilidad Media Alta
Riesgo de error de límites No
⚠️
Limitación del for-each: La variable del for-each es una copia local del elemento. Asignarle un nuevo valor NO modifica el array original. Para modificar elementos, usa el for clásico con índice.

🧊 Arrays multidimensionales

Java permite crear arrays de múltiples dimensiones. Un array bidimensional es, en realidad, un array de arrays: cada posición del array principal contiene una referencia a otro array. Esto permite representar estructuras como matrices, tableros de juego o tablas de datos.

🔹 Declaración y creación de matrices

Java
// Matriz 3×4 (3 filas, 4 columnas)
int[][] matriz = new int[3][4];

// Inicialización directa
int[][] notas = {
    {8, 7, 9},    // Alumno 0
    {6, 8, 7},    // Alumno 1
    {10, 9, 10},  // Alumno 2
    {5, 6, 7}     // Alumno 3
};

// Acceso: notas[fila][columna]
System.out.println(notas[2][0]);  // 10 (Alumno 2, asignatura 0)

🔹 Recorrido de una matriz con bucles anidados

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

// Recorrido con for clásico
for (int i = 0; i < notas.length; i++) {
    double suma = 0;
    for (int j = 0; j < notas[i].length; j++) {
        suma += notas[i][j];
    }
    double media = suma / notas[i].length;
    System.out.printf("Alumno %d: media = %.1f%n", i, media);
}

// Recorrido con for-each
for (int[] fila : notas) {
    for (int nota : fila) {
        System.out.print(nota + " ");
    }
    System.out.println();
}

🔹 Arrays irregulares (jagged arrays)

A diferencia de otros lenguajes, Java permite que cada fila de un array bidimensional tenga un tamaño diferente, creando lo que se conoce como un jagged array o array irregular:

Java
// Array irregular: filas de diferente longitud
int[][] triangulo = new int[4][];  // Solo se define la primera dimensión
triangulo[0] = new int[]{1};
triangulo[1] = new int[]{1, 1};
triangulo[2] = new int[]{1, 2, 1};
triangulo[3] = new int[]{1, 3, 3, 1};

// Recorrer respetando el tamaño de cada fila
for (int[] fila : triangulo) {
    for (int valor : fila) {
        System.out.print(valor + " ");
    }
    System.out.println();
}
// Salida:
// 1
// 1 1
// 1 2 1
// 1 3 3 1

🛠️ La clase java.util.Arrays

La clase utilitaria java.util.Arrays proporciona métodos estáticos muy útiles para trabajar con arrays: ordenación, búsqueda, comparación, relleno y conversión a String. Dominar estos métodos evita reinventar la rueda y produce código más limpio y eficiente.

Java
import java.util.Arrays;

public class MetodosArrays {
    public static void main(String[] args) {

        int[] numeros = {45, 12, 78, 3, 56, 23};

        // 1. toString(): representación legible
        System.out.println(Arrays.toString(numeros));
        // [45, 12, 78, 3, 56, 23]

        // 2. sort(): ordena en orden natural (ascendente)
        Arrays.sort(numeros);
        System.out.println(Arrays.toString(numeros));
        // [3, 12, 23, 45, 56, 78]

        // 3. binarySearch(): busca en array ORDENADO
        int pos = Arrays.binarySearch(numeros, 45);
        System.out.println("45 está en posición: " + pos);
        // 45 está en posición: 3

        // 4. fill(): rellena todas las posiciones
        int[] ceros = new int[5];
        Arrays.fill(ceros, 99);
        System.out.println(Arrays.toString(ceros));
        // [99, 99, 99, 99, 99]

        // 5. equals(): compara contenido (no referencia)
        int[] a = {1, 2, 3};
        int[] b = {1, 2, 3};
        System.out.println(a == b);                     // false (compara referencias)
        System.out.println(Arrays.equals(a, b));          // true  (compara contenido)

        // 6. copyOf(): crea copia con nuevo tamaño
        int[] original = {10, 20, 30};
        int[] copia = Arrays.copyOf(original, 5);
        System.out.println(Arrays.toString(copia));
        // [10, 20, 30, 0, 0]
    }
}
Método Descripción Requisito previo
Arrays.toString(arr) Representación legible del array Ninguno
Arrays.sort(arr) Ordena ascendentemente (in-place) Ninguno
Arrays.binarySearch(arr, key) Busca un valor y devuelve su índice Array ordenado previamente
Arrays.fill(arr, val) Rellena todas las posiciones con un valor Ninguno
Arrays.equals(a, b) Compara el contenido de dos arrays Ninguno
Arrays.copyOf(arr, len) Crea una copia con el tamaño indicado Ninguno
Arrays.deepToString(arr) toString para arrays multidimensionales Ninguno
Arrays.deepEquals(a, b) Compara arrays multidimensionales Ninguno
⚠️
Precaución con binarySearch: Este método solo funciona correctamente sobre arrays previamente ordenados con Arrays.sort(). Si el array no está ordenado, el resultado es indefinido y no se lanza ninguna excepción.

📋 Copia de arrays

Copiar un array en Java no es tan simple como asignar una variable a otra. La asignación solo copia la referencia, no los datos. Existen tres técnicas principales para crear copias independientes.

Java
import java.util.Arrays;

public class CopiaArrays {
    public static void main(String[] args) {

        int[] original = {10, 20, 30, 40, 50};

        // ❌ Esto NO copia: ambas variables apuntan al mismo array
        int[] alias = original;
        alias[0] = 999;
        System.out.println(original[0]);  // 999 — ¡se modificó el original!

        // ✅ Método 1: System.arraycopy() — el más eficiente
        int[] copia1 = new int[original.length];
        System.arraycopy(original, 0, copia1, 0, original.length);

        // ✅ Método 2: Arrays.copyOf() — copia con posible cambio de tamaño
        int[] copia2 = Arrays.copyOf(original, original.length);

        // ✅ Método 3: clone() — copia superficial
        int[] copia3 = original.clone();

        // Las tres copias son independientes del original
        copia1[0] = 1;
        copia2[0] = 2;
        copia3[0] = 3;
        System.out.println(original[0]);  // 999 — no afectado por las copias
    }
}
💡
Copia superficial vs. profunda: Los tres métodos realizan una copia superficial (shallow copy). Para arrays de tipos primitivos, esto es equivalente a una copia profunda. Para arrays de objetos, solo se copian las referencias: los objetos dentro del array siguen siendo los mismos. Si necesitas una copia profunda de un array de objetos, debes clonar cada elemento individualmente.

🚫 Errores frecuentes con arrays

Los arrays son una fuente habitual de errores para programadores novatos (y no tan novatos). Conocer los errores más comunes permite evitarlos desde el principio.

❌ Error 1: Acceder a un índice fuera de rango

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

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

// ❌ Error típico en bucle: usar <= en vez de <
for (int i = 0; i <= nums.length; i++) {  // ← debería ser <
    System.out.println(nums[i]);
}

// ✅ Correcto: usar estrictamente <
for (int i = 0; i < nums.length; i++) {
    System.out.println(nums[i]);
}

❌ Error 2: Confundir asignación de referencia con copia

Java
int[] original = {1, 2, 3};

// ❌ Esto NO crea una copia independiente
int[] copia = original;
copia[0] = 99;
System.out.println(original[0]);  // 99 — ¡el original también cambió!

// ✅ Para copiar, usa Arrays.copyOf()
int[] copiaReal = Arrays.copyOf(original, original.length);

❌ Error 3: Comparar arrays con ==

Java
int[] a = {1, 2, 3};
int[] b = {1, 2, 3};

// ❌ Compara referencias, no contenido
System.out.println(a == b);                     // false

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

❌ Error 4: Imprimir un array directamente con println

Java
int[] datos = {5, 10, 15};

// ❌ Muestra la referencia, no el contenido
System.out.println(datos);
// Salida: [I@6d06d69c  (hash del objeto)

// ✅ Usa Arrays.toString()
System.out.println(Arrays.toString(datos));
// Salida: [5, 10, 15]

🏪 Ejemplo integrador: gestión de inventario

Este programa completo combina todos los conceptos del artículo en un escenario realista: un sistema de gestión de inventario para una pequeña tienda que utiliza arrays paralelos para almacenar nombres de productos, precios y stock.

Java
import java.util.Arrays;

public class GestionInventario {

    // Arrays paralelos: misma posición = mismo producto
    static String[] nombres  = {"Teclado", "Ratón", "Monitor", "Auriculares", "Webcam"};
    static double[] precios  = {45.99, 19.50, 289.00, 35.75, 62.30};
    static int[]    stock    = {120, 200, 45, 80, 60};

    public static void main(String[] args) {

        // 1. Mostrar inventario completo
        mostrarInventario();

        // 2. Calcular valor total del inventario
        double valorTotal = calcularValorTotal();
        System.out.printf("%nValor total del inventario: %.2f €%n", valorTotal);

        // 3. Buscar producto más caro
        int posCaro = buscarMasCaro();
        System.out.printf("Producto más caro: %s (%.2f €)%n",
            nombres[posCaro], precios[posCaro]);

        // 4. Productos con stock bajo (< 50 unidades)
        System.out.println("\n⚠ Productos con stock bajo (< 50 uds):");
        alertaStockBajo(50);

        // 5. Ordenar precios y mostrar ranking
        double[] preciosOrdenados = Arrays.copyOf(precios, precios.length);
        Arrays.sort(preciosOrdenados);
        System.out.println("\nPrecios ordenados: " + Arrays.toString(preciosOrdenados));

        // 6. Generar informe de ventas simulado
        int[][] ventasMensuales = {
            {30, 25, 35},    // Teclado: ene, feb, mar
            {50, 45, 60},    // Ratón
            {10, 8, 12},     // Monitor
            {20, 22, 18},    // Auriculares
            {15, 12, 20}     // Webcam
        };
        informeVentas(ventasMensuales);
    }

    static void mostrarInventario() {
        System.out.println("╔══════════════════╦══════════╦═══════╗");
        System.out.println("║    Producto      ║  Precio  ║ Stock ║");
        System.out.println("╠══════════════════╬══════════╬═══════╣");
        for (int i = 0; i < nombres.length; i++) {
            System.out.printf("║ %-16s ║ %7.2f€ ║  %3d  ║%n",
                nombres[i], precios[i], stock[i]);
        }
        System.out.println("╚══════════════════╩══════════╩═══════╝");
    }

    static double calcularValorTotal() {
        double total = 0;
        for (int i = 0; i < nombres.length; i++) {
            total += precios[i] * stock[i];
        }
        return total;
    }

    static int buscarMasCaro() {
        int pos = 0;
        for (int i = 1; i < precios.length; i++) {
            if (precios[i] > precios[pos]) {
                pos = i;
            }
        }
        return pos;
    }

    static void alertaStockBajo(int umbral) {
        for (int i = 0; i < stock.length; i++) {
            if (stock[i] < umbral) {
                System.out.printf("  → %s: solo %d unidades%n", nombres[i], stock[i]);
            }
        }
    }

    static void informeVentas(int[][] ventas) {
        String[] meses = {"Enero", "Febrero", "Marzo"};
        System.out.println("\n📊 Informe de ventas trimestrales:");
        for (int i = 0; i < ventas.length; i++) {
            int totalProd = 0;
            for (int v : ventas[i]) {
                totalProd += v;
            }
            System.out.printf("  %s: %d uds vendidas (total trimestre)%n",
                nombres[i], totalProd);
        }
    }
}

Este programa produce la siguiente salida:

Salida
╔══════════════════╦══════════╦═══════╗
║    Producto      ║  Precio  ║ Stock ║
╠══════════════════╬══════════╬═══════╣
║ Teclado          ║   45.99€ ║  120  ║
║ Ratón            ║   19.50€ ║  200  ║
║ Monitor          ║  289.00€ ║   45  ║
║ Auriculares      ║   35.75€ ║   80  ║
║ Webcam           ║   62.30€ ║   60  ║
╚══════════════════╩══════════╩═══════╝

Valor total del inventario: 25136.80 €
Producto más caro: Monitor (289.00 €)

⚠ Productos con stock bajo (< 50 uds):
  → Monitor: solo 45 unidades

Precios ordenados: [19.5, 35.75, 45.99, 62.3, 289.0]

📊 Informe de ventas trimestrales:
  Teclado: 90 uds vendidas (total trimestre)
  Ratón: 155 uds vendidas (total trimestre)
  Monitor: 30 uds vendidas (total trimestre)
  Auriculares: 60 uds vendidas (total trimestre)
  Webcam: 47 uds vendidas (total trimestre)

✏️ Ejercicios prácticos

Ejercicio 1: ¿Qué imprime este código? (Comprensión)

Analiza el siguiente fragmento y determina la salida exacta sin ejecutarlo:

Java
int[] a = {5, 10, 15, 20, 25};
int[] b = a;
b[2] = 99;

System.out.println(a[2]);
System.out.println(a.length);
System.out.println(a == b);

int[] c = Arrays.copyOf(a, 3);
System.out.println(Arrays.toString(c));

Ejercicio 2: Invertir un array (Aplicación)

Escribe un método invertir(int[] arr) que invierta el contenido del array in-place (sin crear otro array). Por ejemplo, {1, 2, 3, 4, 5} debe convertirse en {5, 4, 3, 2, 1}.

Ejercicio 3: Matriz de calificaciones (Diseño)

Diseña un programa que gestione las calificaciones de 5 alumnos en 3 asignaturas usando un array bidimensional. El programa debe:

a) Mostrar las notas de cada alumno.
b) Calcular la media de cada alumno.
c) Encontrar el alumno con la media más alta.
d) Contar cuántos alumnos tienen una media superior a 7.0.

❓ Preguntas frecuentes sobre Arrays en Java

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

Un array tiene tamaño fijo definido en su creación y puede almacenar tipos primitivos y objetos. Un ArrayList es una clase de la API Collections con tamaño dinámico que solo almacena objetos (usa autoboxing para primitivos). Los arrays son más eficientes en memoria y velocidad, mientras que ArrayList ofrece métodos como add(), remove() y contains() que simplifican la manipulación.
No, los arrays en Java tienen tamaño fijo e inmutable. Una vez creado con new int[10], no puedes añadir ni eliminar posiciones. Si necesitas un tamaño diferente, debes crear un nuevo array y copiar los elementos con System.arraycopy() o Arrays.copyOf(). Para tamaños dinámicos, usa ArrayList.
Java lanza una excepción ArrayIndexOutOfBoundsException en tiempo de ejecución. A diferencia de lenguajes como C, Java comprueba los límites del array en cada acceso, lo que previene la corrupción de memoria pero obliga al programador a verificar los índices.
Java inicializa automáticamente los elementos de un array según su tipo: los numéricos (int, double, etc.) se inicializan a 0, los boolean a false, los char a '\u0000' y las referencias a objetos a null. Esto garantiza un estado predecible, a diferencia de las variables locales que no se inicializan automáticamente.
Sí, Java permite arrays de cualquier número de dimensiones. Un array tridimensional se declara como int[][][] cubo = new int[3][4][5]. Sin embargo, en la práctica rara vez se usan más de tres dimensiones; para estructuras complejas es preferible utilizar clases con colecciones anidadas.
El método más eficiente es System.arraycopy(), que es una operación nativa optimizada por la JVM. También puedes usar Arrays.copyOf() para crear una copia del tamaño deseado, o el método clone(). Los tres realizan copia superficial; para arrays de objetos, los elementos no se clonan individualmente.
Valora este artículo

💬 Foro de discusión

¿Tienes dudas sobre Arrays en Java? Comparte tu pregunta con la comunidad.

¿Tienes cuenta? o comenta como invitado ↓

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