← Назад к вопросам

Почему нельзя изменить размер массива?

1.6 Junior🔥 161 комментариев
#Коллекции#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Почему нельзя изменить размер массива в Java

Суть проблемы

В Java массивы имеют фиксированный размер, который задается при создании и не может быть изменен. Это фундаментальное проектное решение языка, основанное на том, как работает память.

1. Причина: выделение памяти в куче

Когда вы создаете массив, JVM выделяет непрерывный блок памяти в куче (heap) для хранения элементов:

int[] numbers = new int[5];  // Выделение памяти для 5 элементов

Физический адрес памяти:

Массив на адресе 0x1000:
0x1000: 0
0x1004: 0  (int = 4 байта)
0x1008: 0
0x100C: 0
0x1010: 0

2. Почему нельзя просто расширить

Нехватает места прямо после массива:

Массив numbers:  [0][0][0][0][0]  <- 0x1000 to 0x1013
                                      Нельзя просто добавить сюда!
                                      Там может быть другой объект
Другой объект:  [A][B][C][D]  <- 0x1014 to 0x1020

Если соседняя память занята, расширение невозможно. Пришлось бы перемещать весь соседний объект, что крайне дорого.

3. Производительность и предсказуемость

Фиксированный размер дает гарантии:

  • O(1) доступ: arr[3] = мгновенный доступ к элементу
  • Предсказуемость: нет скрытых аллокаций памяти
  • Быстродействие: no resizing overhead

4. JVM не может гарантировать соседнюю память

JVM работает с кучей, где:

  • Мусоркольектор (GC) перемещает объекты
  • Фрагментация памяти неизбежна
  • Нет гарантий соседней свободной памяти

5. Решение: используй Collection Framework

Для динамических размеров используй ArrayList:

// Неправильно: фиксированный размер
int[] numbers = new int[5];
numbers[5] = 100;  // ArrayIndexOutOfBoundsException!

// Правильно: динамический размер
List<Integer> numbers = new ArrayList<>();
numbers.add(100);  // OK
numbers.add(200);  // OK

Как работает ArrayList (внутри) с расширением:

public class ArrayList<E> {
    private Object[] elementData;
    private int size = 0;
    
    public void add(E e) {
        ensureCapacity(size + 1);
        elementData[size++] = e;
    }
    
    private void ensureCapacity(int minCapacity) {
        if (minCapacity > elementData.length) {
            int newCapacity = elementData.length + (elementData.length >> 1);
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
    }
}

Компромисс ArrayList

ArrayList платит цену:

  • Расширение — это O(n) операция (копирование всех элементов)
  • Больше памяти (часто несколько пустых слотов)
  • Медленнее, чем обычный массив

Но это автоматическое и редкое событие (амортизированное O(1)).

Итог

  • Массивы в Java — это низкоуровневая структура с фиксированным размером
  • Причины: физическая организация памяти, производительность, простота
  • Решение: используй ArrayList, LinkedList или другие Collections для динамических размеров
  • Урок: понимай, когда нужен массив (performance-critical код) и когда нужна Collection