У меня есть объявление массива вроде этого:
int a[];
Здесь a
- массив примитивного типа int
. Где хранится этот массив? Он хранится в куче или стеке? Это примитивный тип int
, все примитивные типы не хранятся в куче.
У меня есть объявление массива вроде этого:
int a[];
Здесь a
- массив примитивного типа int
. Где хранится этот массив? Он хранится в куче или стеке? Это примитивный тип int
, все примитивные типы не хранятся в куче.
Как сказал гурукулки, он хранится в куче. Тем не менее, ваш пост предположил недоразумение, вероятно, из-за того, что какой-то благими намерениями человек пропагандировал миф о том, что "примитивы всегда живут в стеке". Это неверно. Локальные переменные имеют свои значения в стеке, но не все примитивные переменные локальны...
Например, рассмотрим следующее:
public class Foo
{
int value;
}
...
public void someOtherMethod()
{
Foo f = new Foo();
...
}
Теперь, где живет f.value
? Миф предположил бы его в стеке, но на самом деле он является частью нового объекта Foo
и живет на куче 1. (Обратите внимание, что значение f
само является ссылкой и живет в стеке.)
Оттуда это легкий шаг к массивам. Вы можете думать о массиве как о простом переменном - так что new int[3]
немного похоже на класс этой формы:
public class ArrayInt3
{
public readonly int length = 3;
public int value0;
public int value1;
public int value2;
}
1 На самом деле это сложнее, чем это. Разделение стека/кучи в основном является детальностью реализации - я считаю, что некоторые JVM, возможно экспериментальные, могут сказать, когда объект никогда не "ускользает" от метода и может выделить весь объект в стеке. Тем не менее, это концептуально в куче, если вы решите заботиться.
Он будет храниться в куче
потому что массив является объектом в java.
EDIT: если у вас есть
int [] testScores;
testScores = new int[4];
Подумайте об этом коде, как говорится в компиляторе: "Создайте объект массива, который будет содержать четыре ints, и назначьте его ссылочной переменной с именем testScores
. Кроме того, продолжайте и установите каждый элемент int
равным нулю.
Это массив примитивных типов, который сам по себе не является примитивным. Хорошее эмпирическое правило - когда ключевое слово new задействовано, результат будет в куче.
Я просто хотел поделиться несколькими тестами, которые я провел по этому вопросу.
Массив размером 10 миллионов
public static void main(String[] args) {
memInfo();
double a[] = new double[10000000];
memInfo();
}
Выход:
------------------------
max mem = 130.0 MB
total mem = 85.0 MB
free mem = 83.6 MB
used mem = 1.4 MB
------------------------
------------------------
max mem = 130.0 MB
total mem = 130.0 MB
free mem = 48.9 MB
used mem = 81.1 MB
------------------------
Как вы видите, используемый размер кучи увеличивается на ~ 80 МБ, что составляет 10 м * sizeof (double).
Но если мы используем Double вместо double
public static void main(String[] args) {
memInfo();
double a[] = new double[10000000];
memInfo();
}
Выход будет показывать 40 МБ. У нас есть только двойные ссылки, они не инициализируются.
Заполнение его двойным
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
Double qq = 3.1d;
for (int i = 0; i < a.length; i++) {
a[i] = qq;
}
memInfo();
}
Еще 40 МБ. Потому что все они указывают на тот же Double-объект.
Инициализация с помощью double вместо
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
Double qq = 3.1d;
for (int i = 0; i < a.length; i++) {
a[i] = qq.doubleValue();
}
memInfo();
}
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
Линия
a[i] = qq.doubleValue();
эквивалентно
a[i] = Double.valueOf(qq.doubleValue());
что эквивалентно
a[i] = new Double(qq.doubleValue());
Так как каждый раз мы создаем новые двойные объекты, мы продуваем кучу. Это показывает значения внутри класса Double, хранящиеся в куче.
В языке программирования Java массивы являются объектами, динамически создаются и могут быть назначены переменным типа Object.
http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html