Дано: A[] x = new A[5];
(не пишите A x[]
; это законно Java, но вовсе не идиоматично. Считайте это ошибкой стиля. Как неправильное использование кода). Давайте предположим, что это внутри метода (так что это объявление локальной переменной, а не объявление поля).
При этом создается новая локальная переменная с именем 'x', ограниченная указанием на объекты, и может указывать только на экземпляры A[]
или null
и ничего больше, что проверяется как компилятором, так и средой выполнения. Он также создает новый объект массива в куче и устанавливает переменную x
, указывающую на этот вновь созданный объект.
Эта переменная-указатель сама по себе занимает некоторое пространство (4 или 8 байт, в зависимости от виртуальной машины), но она будет в стеке, как в C.
Итак, что же берет new A[5]
в отношении памяти?
Создает новый объект для представления самого массива. Этот объект содержит следующую информацию: Сколько элементов у меня есть, и каков мой тип компонента. Это опять же в отличие от C, где вооружен только указателем на структуру данных массива, вы не знаете, какие данные могут быть, а также не знаете, сколько там данных. В Java это не так, но эта информация (длина и тип) означает, что вам необходимо явно сохранить ее в памяти. Вы можете наблюдать это: x.length
вернет 5, а x.getClass().getComponentType
вернет A.class. На 64-битной виртуальной машине этот объект занимает около 24 байтов (4 для размера, 8 для указателя на тип компонента и несколько дополнительных байтов, потому что объект должен идентифицировать, что он представляет массив).
После этих 24 байтов есть 5 «слотов», и каждый слот занимает столько байтов, сколько требует тип компонента. Сколько это стоит? Зависит от того, что A
.
Если A
: byte
, short
, int
, long
, float
, double
, char
, boolean
или что-либо еще.
Тогда размер компонента (в байтах) составляет соответственно: 1, 2, 4, 8, 8, 4, 8, 2, 1 и X, где X - 4 или 8, в зависимости от виртуальной машины. В наши дни почти всегда 8 (64-битные виртуальные машины).
Виртуальная машина может во время выполнения вставить некоторое пустое пространство в таблицы памяти, потому что современные процессоры действительно действительно не любят иметь дело с вещами, которые не расположены на 64-битных границах. Компиляторы Си делают то же самое.