← Назад к вопросам
Где хранятся примитивы в Java?
2.0 Middle🔥 201 комментариев
#JVM и управление памятью
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Где хранятся примитивы в Java
Примитивы хранятся в Stack (стеке), когда они объявлены как локальные переменные или параметры методов. Если они являются полями класса, то хранятся как часть объекта в Heap (куче).
Stack vs Heap
Stack — быстрая, упорядоченная память
Stack используется для:
- Локальных переменных (включая примитивы)
- Параметров методов
- Ссылок на объекты
- Вызовов методов (call stack)
public void example() {
int age = 25; // примитив int → Stack
double salary = 5000.0; // примитив double → Stack
String name = "Alice"; // ссылка name → Stack, объект String → Heap
}
Heap — общая, медленнее память
Heap используется для:
- Объектов класса
- Массивов
- Строк
- Других объектов
Примитивы в Heap хранятся только как часть объекта.
Пример 1: Локальные примитивы (Stack)
public void localPrimitives() {
int x = 10; // x → Stack, значение 10 → Stack
int y = 20; // y → Stack, значение 20 → Stack
int z = x + y; // z → Stack, значение 30 → Stack
// Stack визуально:
// ┌─────┐
// │ x=10│
// │ y=20│
// │ z=30│
// └─────┘
}
Пример 2: Примитивы в объектах (Heap)
public class Person {
int age; // примитив в объекте → Heap (как часть объекта)
String name; // ссылка → часть объекта в Heap
}
Person person = new Person();
person.age = 25;
person.name = "Bob";
// Визуально:
// Stack: Heap:
// ┌──────────┐ ┌────────────────────┐
// │ person ──┼────→│ Person object │
// └──────────┘ │ ├─ age: 25 │ (примитив в Heap)
// ┌──────────┐ │ ├─ name ────────┐ │
// │ name ref ┼────→│ "Bob" string │ │
// │ └────────────────┘ │
// └────────────────────┘
Пример 3: Примитивы в массивах (Heap)
int[] numbers = {1, 2, 3, 4, 5};
// Stack: Heap:
// ┌──────────┐ ┌─────────────┐
// │ numbers ─┼──────→│ int[] array │
// └──────────┘ │ ├─ [0] = 1 │ (примитивы в Heap)
// │ ├─ [1] = 2 │
// │ ├─ [2] = 3 │
// │ ├─ [3] = 4 │
// │ ├─ [4] = 5 │
// └─────────────┘
Пример 4: Обертки примитивов (Wrapper Classes)
int primitive = 25; // примитив → Stack
Integer wrapper = 25; // ссылка → Stack, объект Integer → Heap
// Stack: Heap:
// ┌──────────┐ ┌──────────┐
// │ primitive│ │ Integer │
// │ = 25 │ │ value:25 │
// └──────────┘ └──────────┘
// ┌──────────┐ ↑
// │ wrapper ─┼────────┘
// └──────────┘
// Автоматическое упаковывание (autoboxing)
Integer boxed = 100; // 100 → Heap в объекте Integer
// Автоматическое распаковывание (unboxing)
int unboxed = boxed; // значение 100 → Stack
Пример 5: Примитивы в методах
public class Calculator {
public int add(int a, int b) {
// Когда вызывается add(5, 3):
// Stack содержит:
// ┌────────────┐
// │ a = 5 │ (параметр)
// │ b = 3 │ (параметр)
// │ result = 8 │ (локальная переменная)
// └────────────┘
int result = a + b;
return result; // значение 8 копируется в caller
}
}
Calculator calc = new Calculator();
int sum = calc.add(5, 3); // sum получает копию значения 8
Lifetime — время жизни примитивов
Stack примитивы (уничтожаются автоматически)
public void demonstrate() {
int x = 10; // создан в Stack
{
int y = 20; // создан в Stack (внутренний блок)
} // y уничтожен, памяти вернута (сразу)
// x еще существует
} // x уничтожен, память вернута
Heap примитивы (в составе объектов)
public void demonstrateHeap() {
Person person = new Person();
person.age = 25; // примитив в Heap
} // person становится недостижимым, Garbage Collector удалит его позже
Pass-by-Value для примитивов
int original = 10;
increment(original);
System.out.println(original); // 10 (не изменилось!)
public void increment(int value) {
value++; // Меняется только копия
}
// Тот же принцип для методов:
public void modify(int num) {
num = 100; // меняет локальную копию, не оригинал
}
int x = 5;
modify(x);
System.out.println(x); // 5
Сравнение примитивов и объектов
// Примитивы:
int a = 10;
int b = 10;
System.out.println(a == b); // true (сравнение значений)
// Объекты (оберки):
Integer x = new Integer(10);
Integer y = new Integer(10);
System.out.println(x == y); // false (разные объекты в Heap)
System.out.println(x.equals(y)); // true (одинаковые значения)
// Integer кэширует значения -128..127
Integer p = 10;
Integer q = 10;
System.out.println(p == q); // true (из кэша)
Integer m = 200;
Integer n = 200;
System.out.println(m == n); // false (не в кэше)
Примитивы в разных контекстах
// 1. Локальная переменная → Stack
public void local() {
int x = 5; // Stack
}
// 2. Поле класса → Heap (часть объекта)
public class Data {
int field = 5; // Heap
}
// 3. Параметр метода → Stack (копия)
public void method(int param) {
// param → Stack, копия переданного значения
}
// 4. Массив примитивов → Heap
int[] array = new int[100]; // array ref → Stack, содержимое → Heap
// 5. Статическое поле → PermGen (Java 7) или MetaSpace (Java 8+)
static int CONSTANT = 5;
Производительность
// Stack — очень быстро (простой указатель вверх)
int x = 10; // Микросекунды
// Heap — медленнее (поиск свободной памяти, GC)
Integer x = new Integer(10); // Микросекунды, но медленнее
// Большие структуры данных лучше на Heap
int[] big = new int[1_000_000]; // Heap
Вывод
- Локальные примитивы → Stack (быстро, автоматическое очищение)
- Примитивы в объектах → Heap (как часть объекта)
- Примитивы в массивах → Heap (как часть массива)
- Обертки примитивов → объекты в Heap
- Pass-by-value — примитивы передаются копией, поэтому изменения внутри метода не влияют на оригинальную переменную