В одном из интервью меня спросили, почему String неизменен
Я ответил так:
Когда мы создаем строку в Java, как
String s1="hello";
тогда, объект будет создан в пуле строк (привет), и s1 будет указывать на привет. Теперь, если мы снова сделаем это,String s2="hello";
другой объект не будет создан, но s2 будет указывать,hello
потому что JVM сначала проверит если тот же объект присутствует в пуле строк или нет. Если его нет, то создается только новый, иначе нет.
Теперь , если предположим , что Java позволяет строку Мутабельном тогда , если мы изменим s1 на hello world
то s2 значение также будет hello world
так String Java , неизменна.
Любое тело, пожалуйста, скажите мне, если мой ответ правильный или неправильный ?
std::string
является изменяемым, но у них также есть пул строк (ну, точнее, пул символьных массивов).Ответы:
String
является неизменным по нескольким причинам, вот резюме:String
в виде сетевых подключений, URL-адресов подключений к базе данных, имен пользователей / паролей и т. Д. Если бы они были изменяемыми, эти параметры можно было бы легко изменить.String
используется в качестве аргументов для загрузки класса. Если он изменчив, это может привести к загрузке неправильного класса (поскольку изменяемые объекты меняют свое состояние).При этом неизменность
String
только означает, что вы не можете изменить его, используя его публичный API. Вы можете фактически обойти нормальный API, используя отражение. Смотрите ответ здесь .В вашем примере, если он
String
был изменчив, рассмотрите следующий пример:источник
String
она изменчива, то загрузчик классов будет принимать переданную строку, делать копию и не изменять ее. Когда вы думаете о проблеме с изменяемымиjava.lang.String
s, подумайте о том, как C ++ решает эту проблему (поскольку она имеет изменяемыеstd::string
s.Разработчики Java решают, что строки являются неизменяемыми из-за следующего аспектного дизайна, эффективности и безопасности .
Строки проектирования создаются в специальной области памяти в куче Java, известной как «Внутренний пул строк». При создании новой строки (не в случае использования конструктора String () или любых других функций String, которые внутренне используют конструктор String () для создания нового объекта String, конструктор String () всегда создает новую строковую константу в пуле, если только мы не вызывая переменную метода intern (), он ищет пул, чтобы проверить, существует ли он уже. Если он существует, вернуть ссылку на существующий объект String. Если строка не является неизменной, изменение строки с одной ссылкой приведет к неправильному значению для других ссылок.
Согласно этой статье на DZone:
источник
Мы не можем быть уверены в том, о чем на самом деле думали Java-дизайнеры при проектировании,
String
но мы можем только заключить эти причины, основываясь на преимуществах, которые мы получаем от неизменяемости строк, некоторые из которых1. Наличие пула констант
Как обсуждалось в статье « Почему хранилище строк в статье String Constant Pool» , каждое приложение создает слишком много строковых объектов, чтобы спасти JVM от первоначального создания большого количества строковых объектов, а затем сбора мусора. JVM хранит все строковые объекты в отдельной области памяти, которая называется пулом констант String, и повторно использует объекты из этого кэшированного пула.
Всякий раз, когда мы создаем строковый литерал, JVM сначала видит, присутствует ли этот литерал в постоянном пуле или нет, и если он там есть, новая ссылка начнет указывать на тот же объект в SCP.
В приведенном выше примере строки объекта со значением
Naresh
получит созданный в SCP только один раз , и все ссылкиa
,b
,c
будет указывать на тот же объект , но что , если мы попытаемся внести изменения вa
напримерa.replace("a", "")
.В идеале,
a
должно иметь значение ,Nresh
ноb
,c
должно оставаться неизменным , поскольку в качестве конечного пользователя мы делаем изменения вa
только. И мы знаемa
,b
,c
все они указывают на тот же объект , так что если мы делаем измененияa
, другие должны также отражать изменения.Но неизменность строки спасает нас от этого сценария и из-за неизменности строкового объекта строковый объект
Naresh
никогда не изменится. Поэтому, когда мы вносим какое-либо изменениеa
вместо строкового объекта,Naresh
JVM создает новый объект, назначает егоa
и затем вносит изменения в этот объект.Таким образом, пул String возможен только из-за неизменности String, и если String не был бы неизменным, то кэширование строковых объектов и их повторное использование не имели бы возможности, потому что любая переменная могла бы изменить значение и повредить другие.
И именно поэтому он обрабатывается JVM очень специально и получил специальную область памяти.
2. Поток безопасности
Объект называется поточно-ориентированным, когда на нем работают несколько потоков, но ни один из них не способен испортить его состояние, и объект в любой момент времени поддерживает одно и то же состояние для каждого потока.
Поскольку мы неизменный объект, никто не может быть изменен после его создания, что делает каждый неизменяемый объект по умолчанию безопасным для потоков. Нам не нужно применять какие-либо меры безопасности потоков, такие как создание синхронизированных методов.
Таким образом, из-за своей неизменной природы строковый объект может совместно использоваться несколькими потоками, и даже если им манипулируют многие потоки, он не изменит своего значения.
3. Безопасность
В каждом приложении нам нужно передать несколько секретов, например, имя пользователя \ пароли, URL-адреса подключения и, в общем, всю эту информацию передают как строковый объект.
Теперь предположим, что если бы String не был неизменным по своей природе, то это вызвало бы серьезную угрозу безопасности приложения, поскольку эти значения могут быть изменены, а если это разрешено, то они могут быть изменены из-за неправильно написанного кода или любого другого лица, которое иметь доступ к нашим ссылкам на переменные.
4. Класс загрузки
Как обсуждалось в разделе Создание объектов с помощью Reflection в Java с примером , мы можем использовать
Class.forName("class_name")
метод для загрузки класса в память, который снова вызывает для этого другие методы. И даже JVM использует эти методы для загрузки классов.Но если вы ясно видите, что все эти методы принимают имя класса как строковый объект, поэтому строки загружаются в класс Java, а неизменяемость обеспечивает безопасность, с которой загружается правильный класс
ClassLoader
.Предположим, что если String не был бы неизменным, и мы пытаемся загрузить то,
java.lang.Object
что изменяетсяorg.theft.OurObject
между ними, и теперь все наши объекты имеют поведение, которое кто-то может использовать для нежелательных вещей.5. Кэширование HashCode
Если мы собираемся выполнить какие-либо операции, связанные с хешированием, для любого объекта, мы должны переопределить
hashCode()
метод и попытаться сгенерировать точный хэш-код, используя состояние объекта. Если состояние объекта меняется, это означает, что его хеш-код также должен измениться.Поскольку String является неизменным, поэтому значение, которое содержит один строковый объект, никогда не изменится, что означает, что его хеш-код также не изменится, что дает классу String возможность кэшировать свой хеш-код во время создания объекта.
Да, объект String кэширует свой хэш-код во время создания объекта, что делает его отличным кандидатом для операций, связанных с хешированием, потому что хэш-код не нужно вычислять заново, что экономит нам некоторое время. Вот почему String в основном используется в качестве
HashMap
ключей.Узнайте больше о том, почему String является неизменным и окончательным в Java .
источник
Наиболее важная причина в соответствии с этой статьей на DZone:
Надеюсь, это поможет вам.
источник
Я прочитал этот пост, почему String является неизменным или окончательным в Java, и предположил, что следующие могут быть наиболее важной причиной:
источник
Ты прав.
String
В Java используется понятиеString Pool
литерала. Когда строка создана и если строка уже существует в пуле, вместо создания нового объекта и возврата его ссылки будет возвращена ссылка на существующую строку. Если строка не является неизменной, изменение строки с одной ссылкой приведет к привести к неправильному значению для других ссылок.Я хотел бы добавить еще одну вещь, поскольку
String
она неизменна, она безопасна для многопоточности, и один экземпляр String может совместно использоваться различными потоками. Это позволяет избежать использования синхронизации для безопасности потоков. Строки неявноthread safe
.источник
String class
FINAL
означает, что вы не можете создать какой-либо класс, чтобы наследовать его, изменить базовую структуру и сделать изменяемым Sting.Другая переменная экземпляра и предоставляемые методы класса String таковы, что вы не можете изменить
String
объект после его создания.Причина, по которой вы добавили, вовсе не делает String неизменной. Это все говорит о том, как String хранится в куче. Также пул строк имеет огромное значение в производительности.
источник
Строка задается как неизменяемая микросистемами Sun, потому что строка может использоваться для хранения в качестве ключа в коллекции карт. StringBuffer является изменяемым. По этой причине его нельзя использовать в качестве ключа в объекте карты.
источник
Наиболее важной причиной того, что String стал неизменным в Java, является соображение безопасности . Следующим будет кеширование .
Я считаю, что другие причины, приведенные здесь, такие как эффективность, параллелизм, дизайн и пул строк, вытекают из того факта, что String in сделан неизменным. Например, String Pool мог быть создан, потому что String был неизменным, а не наоборот.
Проверьте стенограмму интервью Гослинга здесь
источник
В дополнение к отличным ответам я хотел бы добавить несколько моментов. Как и Strings, Array содержит ссылку на начало массива, поэтому, если вы создадите два массива
arr1
и,arr2
и сделали что-то подобноеarr2 = arr1
, ссылка будет такойarr2
же, как,arr1
следовательно, изменение значения в одном из них приведет к изменению, например, другого.Мало того, что это вызовет ошибки в коде, он также может (и будет) использоваться злоумышленником. Предположим, если у вас есть система, которая меняет пароль администратора. Пользователь должен сначала ввести,
newPassword
а затем,oldPassword
если он такойoldPassword
же, какadminPass
программа, сменить парольadminPass = newPassword
. скажем, новый пароль имеет ту же ссылку, что и пароль администратора, поэтому плохой программист может создатьtemp
переменную для хранения пароля администратора до того, как пользователь введет данные, еслиoldPassword
он равен,temp
то в противном случае пароль будет изменен.adminPass = temp
, Кто-то, зная, что может легко ввести новый пароль и никогда не вводить старый пароль и абракадабру, у него есть доступ администратора. Еще одна вещь , которую я не понимаю , когда изучение Струны почему не JVM создать новую строку для каждого объекта и имеют уникальное место в памяти для него , и вы можете просто сделать это с помощьюnew String("str");
Причину вы не хотите , чтобы всегда использоватьnew
это потому что это не эффективно с памятью и медленнее в большинстве случаев читать дальше .источник
Если
HELLO
это ваша строка, то вы не можете изменитьHELLO
наHILLO
. Это свойство называется свойством неизменности.Вы можете иметь несколько строковых переменных-указателей для указания HELLO String.
Но если HELLO - char Array, тогда вы можете изменить HELLO на HILLO. Например,
Ответ:
Языки программирования имеют неизменные переменные данных, чтобы их можно было использовать в качестве ключей в ключе и паре значений. Строковые переменные используются в качестве ключей / индексов, поэтому они неизменны .
источник
С
Security
точки зрения мы можем использовать этот практический пример:источник