Java: являются ли примитивные значения иммутабельными?

Как известно, String в Java является иммутабельным - при создании новой строки её значение записывается в String Pool и в дальнейшем, если создаётся новый String с таким же значением, то новый String не воздаётся, а создаётся только новая ссылка на существующее значение из String Pool. Тему примитивов же деликатно обходят стороной.

Я сейчас в рамках общего развития прохожу курс по Python, и там объясняют, что числа, строки и булевы значения, в частности, являются иммутабельными и при создании заносятся в такой же пул. В дальнейшем, если, скажем, была создана переменная a со значением True, а потом была создана переменная b со значением True, то второй раз значение True создано не будет, а будет создана ссылка на первое значение (совсем как в String в Java).

Хочется прояснить: как в Java с примитивами и обёртками над ними, типа Integer и Long - создаются ли каждый раз новые значения в памяти или же так же присваиваются старые значения?

Благодарю за развёрнутый ответ.


Ответы (1 шт):

Автор решения: Кирилл Малышев

Неизменяемость не означает, что одинаковые неизменяемые объекты должны создаваться только один раз и заноситься в какую-то общую кучу.

Неправильно считать, что все созданные строки заносятся в String Pool. Туда автоматически заносятся литеральные строки

String s = "string";

Но строки созданные с помощью конструктора туда попадут, только если применить к ним метод intern()

String s1 = new String("string");
s == s1 // false
String intern_s1 = s1.intern();
s == intern_s1 // true

Неизменяемость означает только то, что нельзя поменять параметры у созданного объекта.

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

Если примитив определён локально, он располагается на стеке. Т.е. не заносится ни в какую кучу, а его значение буквально хранится там, где оно определено. Когда произодёт выход из соответствующей функции, стек очистится и примитив будет потерян.

Если примитив является атрибутом какого-то объекта, то он хранится в динамической памяти внутри объекта и живёт там, пока живёт объект.

Если мы говорим о классах-обёртках, то они являются неизменяемыми. В Java есть пул целочисленных констант. По умолчанию там находятся целые числа в диапазоне от -128 до 127.

Неизменяемость позволяет гарантировать, что одинаковые объекты можно создавать один раз и хранить их в пуле. Вы, например, можете сами реализовать пул своих объектов. Но это не значит, что над обязательно так делать.

→ Ссылка