Теоретически, стек имеет единственный указатель на место в куче, которое содержит сам массив.Сам массив является просто массивом указателей, которые также указывают на места в куче, которые содержат объекты, на которые вы ссылаетесь.
В Java вы можете в значительной степени рассчитывать на то, что каждый раз, когда вы говорите new ...
, в куче создается пространство.Вообще говоря, всякий раз, когда вы объявляете переменную, компилятор резервирует место в стеке в контексте метода для этой переменной.Для нативных типов это пространство будет содержать фактические байты для представления значения.Для объектов и массивов эта переменная будет содержать ссылку на память.
Так, например, следующим объектам выделены отдельные области памяти, выделенные для них в куче:
new Object[20]
new String("abc")
new List() // This contains a reference to an initial array, which is also on the heap.
Обратите внимание, что естьочень редко, когда new String("abc")
предпочтительнее "abc"
, так как строковые литералы все равно будут существовать в памяти пакета, а строки неизменяемы.Нет смысла выделять дополнительную память для точной копии строки, которая уже существует в памяти.
На практике единственным предостережением является то, что компилятору не обязательно вообще хранить локальные переменные в стеке.Если он определит, что область действия переменной достаточно короткая, она может свободно оптимизировать ссылку на стек и просто использовать для нее регистр.