Я привык делать следующее в C
:
void main() {
String zText = "";
fillString(zText);
printf(zText);
}
void fillString(String zText) {
zText += "foo";
}
И вывод:
foo
Однако в Java это, похоже, не работает. Я предполагаю, потому что String
объект копируется, а не передается по ссылке . Я думал, что строки - это объекты, которые всегда передаются по ссылке.
Что здесь происходит?
java
string
pass-by-reference
Сорен Джонсон
источник
источник
Ответы:
У вас есть три варианта:
Используйте StringBuilder:
Создайте класс контейнера и передайте экземпляр контейнера вашему методу:
Создать массив:
С точки зрения производительности, StringBuilder обычно является лучшим вариантом.
источник
StringBuilder
быстрее,s += "..."
поскольку он не выделяет новые объекты String каждый раз. Фактически, когда вы пишете код Java, какs = "Hello " + name
, тогда компилятор будет генерировать байтовый код, который создаетStringBuilder
и вызываетappend()
два раза.В Java ничего не передается по ссылке . Все передается по значению . Ссылки на объекты передаются по значению. Кроме того, строки неизменяемы . Поэтому, когда вы добавляете к переданной строке, вы просто получаете новую строку. Вы можете использовать возвращаемое значение или передать вместо него StringBuffer.
источник
Происходит то, что ссылка передается по значению, т. Е. Передается копия ссылки. Ничто в java не передается по ссылке, и поскольку строка является неизменной, это присваивание создает новый строковый объект, на который теперь указывает копия ссылки . Исходная ссылка все еще указывает на пустую строку.
Это будет то же самое для любого объекта, т. Е. Установка для него нового значения в методе. Приведенный ниже пример просто делает то, что происходит, более очевидным, но объединение строк - это одно и то же.
источник
java.lang.String является неизменной.
Я ненавижу вставлять URL-адреса, но https://docs.oracle.com/javase/10/docs/api/java/lang/String.html важно для вас, чтобы читать и понимать, если вы находитесь в java-land.
источник
объекты передаются по ссылке, примитивы передаются по значению.
Строка не является примитивом, это объект, и это особый случай объекта.
Это для экономии памяти. В JVM есть пул строк. Для каждой созданной строки JVM будет пытаться определить, существует ли такая же строка в пуле строк, и указать на нее, если она уже была.
/* ВЫВОД */
== проверяет адрес памяти (ссылка), а .equals проверяет содержимое (значение)
источник
Все аргументы в Java передаются по значению. Когда вы передаете a
String
в функцию, переданное значение является ссылкой на объект String, но вы не можете изменить эту ссылку, и базовый объект String является неизменным.Назначение
эквивалентно:
То есть он (локально) переназначает параметр
zText
как новую ссылку, которая указывает на новую ячейку памяти, в которой находится новая,String
которая содержит оригинальное содержимоеzText
с"foo"
добавленным.Исходный объект не изменяется, а
main()
локальная переменная метода по-zText
прежнему указывает на исходную (пустую) строку.печатает:
Если вы хотите изменить строку, вы можете, как уже было отмечено, использовать
StringBuilder
какой-либо контейнер (массив,AtomicReference
или пользовательский класс контейнера), который дает вам дополнительный уровень косвенности указателя. В качестве альтернативы просто верните новое значение и назначьте его:печатает:
Вероятно, это наиболее похожее на Java решение в общем случае - см. Пункт « Эффективная Java » «Постоянная предпочтительность».
Тем не менее, как уже отмечалось,
StringBuilder
часто это даст вам лучшую производительность - если у вас есть много возможностей добавления, особенно внутри цикла, используйтеStringBuilder
.Но попробуйте обойтись неизменяемым,
Strings
а не изменяемым,StringBuilders
если вы можете - ваш код будет легче читать и легче поддерживать. Подумайте оfinal
настройке параметров и настройке среды IDE для предупреждения о переназначении параметра метода на новое значение.источник
Строка является неизменным объектом в Java. Вы можете использовать класс StringBuilder для выполнения работы, которую вы пытаетесь выполнить, следующим образом:
Другой вариант - создать класс с String в качестве переменной области (крайне не рекомендуется) следующим образом:
источник
Ответ прост. В Java строки неизменны. Следовательно, все равно, что использовать модификатор 'final' (или 'const' в C / C ++). Таким образом, после назначения вы не можете изменить его так, как вы это сделали.
Вы можете изменить который значение , к которому струнные точки, но вы не можете изменить фактическое значение, которое эта строка в данный момент указывает.
То есть.
String s1 = "hey"
, Вы можете сделатьs1 = "woah"
, и это совершенно нормально, но вы не можете на самом деле изменить базовое значение строки (в данном случае: «эй»), чтобы оно было чем-то другим после присвоения с помощью plusEquals и т. Д. (Т.е.s1 += " whatup != "hey whatup"
).Для этого используйте классы StringBuilder или StringBuffer или другие изменяемые контейнеры, а затем просто вызовите .toString (), чтобы преобразовать объект обратно в строку.
примечание: строки часто используются в качестве ключей хеширования, поэтому это одна из причин их неизменности.
источник
=
на ссылку НИКОГДА не влияет на объект, на который он указывал, независимо от класса.String - это специальный класс в Java. Это Потокобезопасный, что означает «После создания экземпляра String содержимое экземпляра String никогда не изменится».
Вот что происходит
Сначала компилятор Java получит значение экземпляра zText String, затем создаст новый экземпляр String, значением которого является zText, добавив «foo». Итак, вы знаете, почему экземпляр, на который указывает zText, не изменился. Это совершенно новый экземпляр. Фактически, даже String "foo" является новым экземпляром String. Таким образом, для этого оператора Java создаст два экземпляра String, один - «foo», другой - значение zText append «foo». Правило простое: значение экземпляра String никогда не изменится.
Для метода fillString вы можете использовать StringBuffer в качестве параметра или изменить его следующим образом:
источник
Строки являются неизменяемыми в Java.
источник
Это работает использовать StringBuffer
Еще лучше использовать StringBuilder
источник
Строка неизменна в Java. Вы не можете изменить / изменить существующий строковый литерал / объект.
String s = "Hello"; S = S + "Привет";
Здесь предыдущая ссылка s заменяется новой ссылкой s, указывающей на значение «HelloHi».
Однако для обеспечения изменчивости у нас есть StringBuilder и StringBuffer.
StringBuilder s = new StringBuilder (); s.append ( "Привет");
это добавляет новое значение «Привет» к той же ссылке s. //
источник
У Аарона Дигуллы пока лучший ответ. Вариантом его второго варианта является использование класса-обертки или контейнера MutableObject из библиотеки commons lang версии 3+:
Вы сохраняете объявление класса контейнера. Недостатком является зависимость от общего языка lang lib. Но в lib есть много полезных функций, и почти любой большой проект, над которым я работал, использовал его.
источник
Для передачи объекта (включая String) по ссылке в java вы можете передать его как член окружающего адаптера. Решение с универсальным здесь:
источник
Для кого-то, кто более любопытен
источник