← Назад к вопросам

Где хранится переменная в методе с типом Integer?

1.3 Junior🔥 191 комментариев
#JVM и управление памятью

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Где хранится переменная типа Integer в методе

Это классический вопрос о том, как Java управляет памятью. Ответ зависит от контекста, и нужно разбираться в разнице между примитивными типами и классами-обёртками.

Stack vs Heap

Примитив int (в stack)

public void method() {
    int x = 10;  // Переменная x хранится в STACK
    // Stack: [x: 10]
}

Примитив int хранится прямо в stack-памяти (что это находится на стеке вызовов потока).

Класс-обёртка Integer (ссылка в stack, объект в heap)

public void method() {
    Integer x = 10;  // Переменная x — это ССЫЛКА на объект Integer
    // Stack: [x: 0x1F4A] (адрес в heap)
    // Heap:  [0x1F4A: Integer объект с value=10]
}

Переменная x (ссылка) хранится в stack, но сам объект Integer хранится в heap.

Детальное объяснение

1. Переменная Integer x = 10

public void demoInteger() {
    Integer x = 10;  // Автобоксинг: Integer.valueOf(10)
    Integer y = 10;  // Может быть тот же объект (из кэша)
    Integer z = 1000; // Новый объект (вне диапазона кэша)
    
    System.out.println(x == y);  // true (кэш от -128 до 127)
    System.out.println(x == z);  // false (разные объекты)
}

Что происходит:

  1. Stack содержит три ссылки: x, y, z
  2. Heap содержит объекты Integer
  3. x и y могут указывать на один и тот же объект (Integer кэширует значения от -128 до 127)
  4. z указывает на другой объект
Stack:
┌─────┐
│ x   ├───┐
├─────┤   │ (оба указывают на
│ y   ├───┼──> на один объект,
├─────┤   │   благодаря кэшу)
│ z   ├──┐└───────────────────────┐
└─────┘  │                        │
         │ Heap:                  │
         │ ┌────────────────────┐ │
         └─>│ Integer(10)        │ │
           │ value: 10          │ │
           └────────────────────┘ │
                                  │
           ┌────────────────────┐ │
           │ Integer(1000)      │<┘
           │ value: 1000        │
           └────────────────────┘

2. Параметр метода Integer param

public void processInteger(Integer param) {
    // param — это локальная переменная метода
    // Ссылка хранится в STACK
    // Объект Integer хранится в HEAP
    
    System.out.println(param);  // Чтение из heap через ссылку из stack
}

// Вызов
Integer value = 50;
processInteger(value);  // Передаём ссылку (не копируем объект)

3. Поле класса Integer

public class User {
    private Integer age;  // Ссылка хранится в HEAP (как часть объекта User)
    
    public void setAge(Integer age) {
        this.age = age;  // Сохраняем ссылку на Integer объект
    }
}

// Когда создаём пользователя:
User user = new User();
user.setAge(25);

// Память:
// Stack: [user: 0x2F3A] (ссылка на User объект)
// Heap:
//   [0x2F3A] User {
//     age: 0x3B5C (ссылка на Integer)
//   }
//   [0x3B5C] Integer {
//     value: 25
//   }

Тонкости Integer

Кэширование Integer

public class IntegerCaching {
    public static void main(String[] args) {
        Integer a = 100;    // Из кэша
        Integer b = 100;    // Из кэша
        Integer c = new Integer(100);  // Новый объект
        
        System.out.println(a == b);  // true (один и тот же объект)
        System.out.println(a == c);  // false (разные объекты)
        System.out.println(a.equals(c));  // true (значения равны)
        
        // Кэш работает от -128 до 127
        Integer d = 128;   // Вне кэша
        Integer e = 128;   // Вне кэша
        System.out.println(d == e);  // false!
    }
}

Почему это важно

public class Example {
    public static void main(String[] args) {
        Integer x = new Integer(10);
        Integer y = new Integer(10);
        Integer z = 10;
        
        // Stack содержит три ссылки
        System.out.println(x == y);   // false (разные объекты)
        System.out.println(y == z);   // false или true в зависимости от кэша
        System.out.println(x.equals(y));  // true (значения равны)
    }
}

Сравнение: int vs Integer

int (примитив)

public void intExample() {
    int a = 10;       // Stack: значение 10
    int b = 10;       // Stack: значение 10 (разные переменные)
    int c = a;        // Stack: копия значения 10
    
    // int сравнивают через ==
    System.out.println(a == b);  // true
    System.out.println(a == c);  // true
    
    // Размер: 4 байта
    // Диапазон: -2^31 до 2^31-1
}

Integer (класс-обёртка)

public void integerExample() {
    Integer a = 10;       // Stack: ссылка, Heap: объект Integer
    Integer b = 10;       // Stack: ссылка, Heap: возможно тот же объект
    Integer c = a;        // Stack: копия ссылки
    
    // Integer сравнивают через equals()
    System.out.println(a == b);        // true (из кэша)
    System.out.println(a.equals(b));   // true
    
    // Размер: 16-24 байта (overhead объекта)
    // Диапазон: -2^31 до 2^31-1
}

Автобоксинг и анбоксинг

public void autoboxing() {
    // Автобоксинг: int -> Integer
    Integer x = 10;  // Эквивалентно Integer.valueOf(10)
    
    // Анбоксинг: Integer -> int
    int y = x;  // Эквивалентно x.intValue()
    
    // Полный контроль
    Integer explicit = Integer.valueOf(20);
    int unbox = explicit.intValue();
}

Практический пример: Где находится память

public class MemoryExample {
    private Integer fieldInteger;  // ССЫЛКА в heap (часть объекта класса)
    
    public void methodExample() {
        int localInt = 10;           // ЗНАЧЕНИЕ в stack
        Integer localInteger = 10;   // ССЫЛКА в stack, ОБЪЕКТ в heap
        
        List<Integer> list = new ArrayList<>();
        list.add(localInteger);      // ССЫЛКА в heap (часть ArrayList)
        
        // В конце метода:
        // - localInt и localInteger удаляются из stack
        // - если на localInteger нет других ссылок, объект становится eligible для GC
    }
    
    public Integer returnInteger() {
        Integer result = 100;  // ССЫЛКА в stack, ОБЪЕКТ в heap
        return result;         // Возвращаем ссылку (объект остаётся в heap)
    }
}

GC и Integer

public class GCExample {
    public static void main(String[] args) {
        Integer a = 1000000;
        {
            Integer b = 2000000;  // Новый объект Integer
            System.out.println(b);  // Используем
        }  // b выходит из scope, но объект ещё в heap
        // GC может собрать этот объект позже
        
        System.gc();  // Просим GC (но это не гарантия)
        System.out.println(a);  // a всё ещё живой
    }
}

Итоговая схема

public void complete() {
    // LOCAL VARIABLES (Stack):
    int primitiveInt = 5;           // ┐ Прямо в stack
    Integer wrappedInt = 10;        // ├─ Ссылка в stack
    Integer[] array = new Integer[3]; // ├─ Ссылка на массив в stack
    
    // HEAP:
    // ┌─ Integer объект value=10 (из кэша или новый)
    // ├─ Integer[] массив (содержит ссылки)
    // └─ Элементы массива (Integer объекты)
}

Выводы

ПеременнаяГде хранитсяАдресЗначение
int xStackНепосредственно5
Integer xStack (ссылка)0x1F4AОбъект в heap
Integer[] arrStack (ссылка)0x2A3BМассив в heap
User.age (Integer)Heap (часть объекта)-Ссылка на Integer

Ключевой момент: Переменная типа Integer x — это ссылка, которая хранится в stack, но указывает на объект Integer, который находится в heap. Это коренной отличает классы-обёртки от примитивных типов.

Где хранится переменная в методе с типом Integer? | PrepBro