Это может быть самый тупой вопрос, который когда-либо задавался, но я думаю, что это довольно запутанно для новичка на Java.
- Может кто-нибудь уточнить, что подразумевается под неизменным ?
- Почему
String
неизменный? - Каковы преимущества / недостатки неизменяемых объектов?
- Почему изменяемый объект, например,
StringBuilder
должен быть предпочтительнее, чем String и наоборот?
Хороший пример (на Java) будет очень полезен.
java
string
immutability
ashokgelal
источник
источник
Ответы:
Неизменяемый означает, что, как только конструктор для объекта завершит выполнение, этот экземпляр не может быть изменен.
Это полезно, поскольку это означает, что вы можете передавать ссылки на объект, не беспокоясь о том, что кто-то еще изменит его содержимое. Особенно при работе с параллелизмом нет проблем с блокировкой объектов, которые никогда не меняются
например
Foo
не нужно беспокоиться о том, что вызывающая сторонаgetValue()
может изменить текст в строке.Если вы представляете класс, похожий на
Foo
, но с членом,StringBuilder
а неString
как член, вы можете видеть, что вызывающая сторонаgetValue()
может изменятьStringBuilder
атрибутFoo
экземпляра.Также остерегайтесь различных видов неизменности, которые вы можете найти: Эрик Липперт написал статью об этом в блоге . По сути, вы можете иметь объекты, чей интерфейс является неизменным, но за кулисами фактически измененное частное состояние (и, следовательно, не может быть безопасно разделено между потоками).
источник
Неизменяемый объект - это объект, в котором внутренние поля (или, по крайней мере, все внутренние поля, которые влияют на его внешнее поведение) не могут быть изменены.
Есть много преимуществ для неизменяемых строк:
Производительность: выполните следующую операцию:
Базовый C для метода substring (), вероятно, выглядит примерно так:
Обратите внимание, что ни один из символов не должен быть скопирован! Если бы объект String был изменяемым (символы могли бы измениться позже), вам бы пришлось скопировать все символы, в противном случае изменения символов в подстроке будут отражены в другой строке позже.
Параллельность: если внутренняя структура неизменяемого объекта является действительной, она всегда будет действительной. Нет никаких шансов, что разные потоки могут создать недопустимое состояние в этом объекте. Следовательно, неизменяемые объекты являются потокобезопасными .
Сборка мусора: сборщику мусора гораздо проще принимать логические решения относительно неизменных объектов.
Однако есть и недостатки неизменности:
Производительность: Подожди, я думал, ты сказал, что производительность была неизменной! Ну, это иногда, но не всегда. Возьмите следующий код:
Обе строки заменяют четвертый символ буквой «а». Второй фрагмент кода не только более читабелен, но и быстрее. Посмотрите, как вам придется делать основной код для foo. Подстроки просты, но теперь, когда в пятой позиции уже есть символ и что-то еще может ссылаться на foo, вы не можете просто изменить его; Вы должны скопировать всю строку (конечно, некоторые из этих функций абстрагированы в функции в реальном базовом C, но суть здесь в том, чтобы показать код, который выполняется все в одном месте).
Обратите внимание, что concatenate вызывается дважды, что означает, что вся строка должна быть зациклена! Сравните это с кодом C для
bar
операции:Операция с изменяемой строкой, очевидно, намного быстрее.
В заключение: в большинстве случаев вам нужна неизменная строка. Но если вам нужно много добавлять и вставлять в строку, вам нужна изменчивость для скорости. Если вы хотите использовать преимущества безопасности параллелизма и сборки мусора, ключом является сохранение ваших изменяемых объектов локальными для метода:
Поскольку
mutable
объект является локальной ссылкой, вам не нужно беспокоиться о безопасности параллелизма (когда-либо к нему обращается только один поток). А поскольку на него больше нигде нет ссылок, он размещается только в стеке, поэтому он освобождается после завершения вызова функции (вам не нужно беспокоиться о сборке мусора). И вы получаете все преимущества производительности как изменчивости, так и неизменности.источник
Passing pointers because Java is pass-by-reference
Разве ява не является «передачей по значению»?На самом деле String не является неизменным, если вы используете определение Википедии, предложенное выше.
Состояние String меняет пост-конструкцию. Взгляните на метод hashcode (). String кэширует значение хеш-кода в локальном поле, но не вычисляет его до первого вызова hashcode (). Эта ленивая оценка хеш-кода ставит String в интересное положение как неизменного объекта, состояние которого изменяется, но нельзя наблюдать, как он изменился без использования отражения.
Так что, возможно, определение неизменяемости должно быть объектом, который, как нельзя наблюдать, изменился.
Если состояние изменяется в неизменяемом объекте после того, как он был создан, но никто не может видеть его (без отражения), остается ли объект неизменным?
источник
Неизменяемые объекты - это объекты, которые нельзя изменить программно. Они особенно хороши для многопоточных сред или других сред, где более чем один процесс может изменять (изменять) значения в объекте.
Однако, чтобы уточнить, StringBuilder на самом деле является изменяемым объектом, а не неизменным. Обычная строка Java является неизменной (это означает, что после ее создания вы не можете изменить базовую строку без изменения объекта).
Например, предположим, что у меня есть класс ColoredString, который имеет значение String и цвет String:
В этом примере ColoredString называется изменяемой, поскольку вы можете изменить (изменить) одно из его ключевых свойств, не создавая новый класс ColoredString. Причина, по которой это может быть плохо, например, допустим, у вас есть приложение с графическим интерфейсом, которое имеет несколько потоков, и вы используете ColoredStrings для печати данных в окне. Если у вас есть экземпляр ColoredString, который был создан как
Тогда вы ожидаете, что строка всегда будет синей. Если другой поток, однако, получил этот экземпляр и вызвал
Вы бы внезапно и, вероятно, неожиданно, теперь получили «Красную» строку, когда хотели «Голубую». Из-за этого неизменные объекты почти всегда предпочтительнее при передаче экземпляров объектов вокруг. Когда у вас есть случай, когда изменяемые объекты действительно необходимы, тогда вы обычно защищаете объект, только передавая копии из вашей конкретной области контроля.
Напомним, что в Java java.lang.String является неизменным объектом (его нельзя изменить после создания), а java.lang.StringBuilder является изменяемым объектом, поскольку его можно изменить без создания нового экземпляра.
источник
String s1 = "Старая строка";
Строка s2 = s1;
s1 = "Новая строка";
источник
«неизменный» означает, что вы не можете изменить значение. Если у вас есть экземпляр класса String, любой вызываемый вами метод, который, кажется, изменяет значение, фактически создаст другую String.
Чтобы сохранить изменения, вы должны сделать что-то вроде этого foo = foo.sustring (3);
Неизменность и изменчивость могут быть смешными, когда вы работаете с коллекциями. Подумайте, что произойдет, если вы используете изменяемый объект в качестве ключа для карты, а затем измените значение (совет: подумайте об
equals
иhashCode
).источник
java.time
Это может быть немного поздно, но чтобы понять, что такое неизменный объект, рассмотрим следующий пример из нового Java 8 Date and Time API ( java.time ). Как вы, наверное, знаете, все объекты даты из Java 8 являются неизменяемыми, поэтому в следующем примере
Вывод:
Это печатает тот же год, что и начальная дата, потому что
plusYears(2)
возвращает новый объект, поэтому старая дата остается неизменной, потому что это неизменный объект. После создания вы не можете его изменить, а переменная даты все еще указывает на него.Таким образом, этот пример кода должен захватывать и использовать новый объект, созданный и возвращенный этим вызовом
plusYears
.источник
Мне очень нравится объяснение из SCJP Sun Certified Programmer для Java 5 Учебное пособие .
источник
Объекты, которые являются неизменяемыми, не могут изменить свое состояние после того, как они были созданы.
Существуют три основные причины, по которым вы всегда можете использовать неизменяемые объекты, и все это поможет уменьшить количество ошибок, которые вы вносите в свой код:
Есть также некоторые другие оптимизации, которые вы могли бы выполнить в коде, когда знаете, что состояние объекта является неизменным - например, кеширование вычисленного хэша - но это оптимизации и, следовательно, они не так интересны.
источник
Одно из значений связано с тем, как значение хранится в компьютере. Например, для строки .Net это означает, что строку в памяти нельзя изменить. Когда вы думаете, что изменяете ее, вы фактически создаете новую строка в памяти и указание существующей переменной (которая является просто указателем на фактическую коллекцию символов где-то еще) на новую строку.
источник
s1="Hi"
: объектs1
был создан со значением «Привет» в нем.s2=s1
: объектs2
создается со ссылкой на объект s1.s1="Bye"
: значение предыдущегоs1
объекта не изменяется, посколькуs1
имеет тип String, а тип String является неизменяемым типом, вместо этого компилятор создает новый объект String со значением «Bye» иs1
ссылкой на него. здесь, когда мы печатаемs2
значение, результатом будет «Привет», а не «Пока», посколькуs2
ссылка на предыдущийs1
объект имеет значение «Привет».источник
Неизменяемый означает, что как только объект создан, ни один из его членов не изменится.
String
является неизменным, так как вы не можете изменить его содержание. Например:В приведенном выше коде строка s1 не изменилась, другой объект (
s2
) был создан с помощьюs1
.источник
Неизменяемые просто означают неизменяемые или неизменяемые. После создания строкового объекта его данные или состояние не могут быть изменены.
Рассмотрим приведенный ниже пример,
Давайте разберемся с диаграммой ниже,
На этой диаграмме вы можете увидеть новый объект, созданный как «Мир будущего». Но не меняйте «Будущее».
Because String is immutable
,s
, все еще обратитесь к "Будущему". Если вам нужно позвонить "Мир будущего",Почему строковые объекты неизменяемы в Java?
источник
Однажды созданный, не может быть изменен. Рассмотрим класс, экземпляр которого может использоваться в качестве ключа для хеш-таблицы или аналогичного. Ознакомьтесь с рекомендациями по Java.
источник
Неизменные объекты
Объект считается неизменным, если его состояние не может измениться после его создания. Максимальная опора на неизменяемые объекты широко признана в качестве разумной стратегии для создания простого и надежного кода.
Неизменяемые объекты особенно полезны в параллельных приложениях. Так как они не могут изменить состояние, они не могут быть повреждены из-за помех потока или наблюдаются в несовместимом состоянии.
Программисты часто неохотно используют неизменные объекты, потому что они беспокоятся о стоимости создания нового объекта, а не об обновлении объекта на месте. Влияние создания объекта часто переоценивается и может быть компенсировано некоторыми из преимуществ, связанных с неизменяемыми объектами. К ним относятся снижение накладных расходов из-за сбора мусора и устранение кода, необходимого для защиты изменяемых объектов от повреждения.
Следующие подразделы берут класс, экземпляры которого являются изменяемыми, и получают класс с неизменяемыми экземплярами из него. При этом они дают общие правила для такого рода преобразования и демонстрируют некоторые преимущества неизменных объектов.
Источник
источник
Поскольку принятый ответ не отвечает на все вопросы. Я вынужден дать ответ через 11 лет и 6 месяцев.
Надеюсь, вы имели в виду неизменный объект (потому что мы могли бы подумать об неизменной ссылке ).
Объект является неизменным : если он создан, он всегда представляет одно и то же значение (не имеет метода, который изменяет значение).
Соблюдайте приведенное выше определение, которое можно проверить, изучив исходный код Sting.java .
безопаснее от ошибок.
легче понять.
и более готов к изменениям.
Сужение вопроса. Зачем нам нужен изменчивый StringBuilder в программировании? Обычно его используют для объединения большого количества строк, например:
Используя неизменяемые строки, это делает много временных копий - первое число строки («0») фактически копируется n раз в процессе построения финальной строки, второе число копируется n-1 раз, и так на. На самом деле копирование всего этого времени занимает O (n2), хотя мы объединяли только n элементов.
StringBuilder предназначен для минимизации этого копирования. Он использует простую, но умную внутреннюю структуру данных, чтобы вообще не копировать до самого конца, когда вы запрашиваете окончательную строку с вызовом toString ():
Хорошая производительность - одна из причин, почему мы используем изменяемые объекты. Еще одно удобное совместное использование: две части вашей программы могут общаться более удобно, разделяя общую изменчивую структуру данных.
Больше можно найти здесь: https://web.mit.edu/6.005/www/fa15/classes/09-immutability/#useful_immutable_types
источник
Неизменяемый объект - это объект, который нельзя изменить после его создания. Типичным примером являются строковые литералы.
Язык программирования AD, который становится все более популярным, имеет понятие «неизменяемость» через ключевое слово «инвариант». Прочтите статью об этом доктора Добба - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29 . Это прекрасно объясняет проблему.
источник