Что хранится в переменной в Java?

Ответ

Содержимое переменной в Java зависит от её типа:

  1. Для примитивных типов (int, double, boolean, char и т.д.): Переменная хранит непосредственно значение.

    int count = 42;      // В переменной `count` хранится число 42.
    boolean flag = true; // В переменной `flag` хранится значение true.

    Место хранения: Стек (stack frame метода).

  2. Для ссылочных типов (классы, интерфейсы, массивы): Переменная хранит ссылку (указатель, адрес) на объект, расположенный в куче (heap).

    String message = "Hello"; // `message` хранит ссылку на объект String "Hello".
    List<Integer> list = new ArrayList<>(); // `list` хранит ссылку на новый объект ArrayList.
    Object obj = null;         // `obj` хранит специальную ссылку null, не указывающую на объект.

    Место хранения: Сама ссылка — в стеке. Объект, на который она указывает, — в куче.

Важное следствие: При присваивании одной ссылочной переменной другой копируется ссылка, а не объект. Обе переменные начинают указывать на один и тот же объект в памяти.

StringBuilder a = new StringBuilder("Hello");
StringBuilder b = a; // b и a теперь ссылаются на один объект
b.append(" World");
System.out.println(a); // Выведет: "Hello World"

Ответ 18+ 🔞

А, слушай, вот эта тема про переменные в Java — она, блядь, как будто простая, а потом бац — и ты уже в жопе, потому что не понял, где что лежит. Ёпта, давай разжую, как есть.

Вот смотри, есть у нас два главных вида переменных, как два сорта говна: одни примитивные, другие — ссылочные. И хранятся они по-разному, сука.

Первые — примитивы. Это как int, double, boolean, char — вся эта хуйня. Тут всё просто, как три копейки. Переменная хранит само значение, прямо в себе. Как будто в кармане заначку держишь.

int count = 42;      // В `count` лежит прямо число 42, ни хуя больше.
boolean flag = true; // В `flag` лежит прямо `true`. Всё, пиздец.

И где эта заначка лежит? В стеке, блядь! В том самом стеке метода, который вызвали. Удобно, быстро, и никаких тебе хитрых ссылок.

А теперь вторые — ссылочные. Это уже поинтереснее, ёпта. Сюда входят все классы, интерфейсы и, мать их, массивы. Тут переменная — это не сам объект, а ссылка на него. Как записка с адресом, где этот объект спрятан.

String message = "Hello"; // `message` — это не "Hello", а бумажка с адресом, где "Hello" лежит.
List<Integer> list = new ArrayList<>(); // `list` — адресок на новенький `ArrayList`.
Object obj = null;         // А это — пустая бумажка, адреса нет. Просто `null`, нихуя не указывает.

И где же всё это безобразие находится? Сама бумажка-ссылка — в стеке, как и примитив. А вот объект, на который она указывает — тот уже в куче (heap), в этой большой общей помойке памяти. Он там живёт своей жизнью, пока на него кто-то ссылается.

А теперь главный подвох, из-за которого все обоссываются! Когда ты одну ссылочную переменную присваиваешь другой, ты копируешь бумажку с адресом, а не сам объект! Получается, две бумажки ведут к одной и той же хате.

StringBuilder a = new StringBuilder("Hello");
StringBuilder b = a; // Скопировали бумажку! Теперь `b` и `a` смотрят на один и тот же `StringBuilder`.
b.append(" World"); // Пришли по адресу и нахуярили в общий объект.
System.out.println(a); // Выведет: "Hello World". Охуел? А я нет. Так и задумано.

Вот и вся магия, блядь. Запомни: примитивы — это значение в кармане, ссылки — бумажка с адресом на объект в куче. И не путай, а то получишь NullPointerException прямо в ебальник.