У мене є таке оголошення масиву:
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, можливо експериментальні, можуть визначити, коли об'єкт ніколи не "втікає" від методу, і можуть виділити весь об'єкт у стек. Однак це концептуально на купі, якщо ви вирішите доглядати.
String
підтримка char[]
. Я вважаю, що буквальні рядки зберігаються у загальнодоступному пулі постійних; для оптимізації GC це означало б, що масиви резервної копії слід зберігати так само (інакше пул констант доведеться сканувати під час будь-якого циклу GC, де масив резервної копії в іншому випадку буде прийнятним для збору).
Він буде зберігатися в купі
тому що масив є об'єктом у Java.
EDIT : якщо у вас є
int [] testScores;
testScores = new int[4];
Подумайте про цей код, як про те, що він сказав компілятору: "Створіть об’єкт масиву, який міститиме чотири вставки, і призначте його посилальній змінній із назвою testScores
. Крім того, продовжуйте і встановлюйте кожен int
елемент нульовим. Дякую."
-g
опцію компілятору. В іншому випадку його буде оптимізовано.
Це масив примітивних типів, який сам по собі не є примітивним. Хорошим емпіричним правилом є те, що коли задіяно нове ключове слово, результат буде в купі.
Я просто хотів поділитися кількома тестами, які я провів з цього питання.
Масив розміром 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 м * розмір (подвійний).
Але якщо ми маємо використовувати Double замість double
public static void main(String[] args) {
memInfo();
Double a[] = new Double[10000000];
memInfo();
}
Вихід покаже 40 Мб. У нас є лише подвійні посилання, вони не ініціалізовані.
Наповнивши його 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;
}
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.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 об'єкти кожного разу, ми здуваємо купу. Це показує, що значення всередині класу Double зберігаються в купі.
У мові програмування Java масиви є об'єктами, створюються динамічно і можуть бути призначені змінним типу Object.
http://java.sun.com/docs/books/jls/second_edition/html/arrays.doc.html