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.
Неизменяемость позволяет гарантировать, что одинаковые объекты можно создавать один раз и хранить их в пуле. Вы, например, можете сами реализовать пул своих объектов. Но это не значит, что над обязательно так делать.