Как мне скопировать строки в Java?

199
    String s = "hello";
    String backup_of_s = s;
    s = "bye";

На этом этапе переменная резервной копии все еще содержит исходное значение «привет» (это из-за неизменности в String, верно?).

Но действительно ли безопасно копировать строки этим методом (что, конечно, небезопасно копировать обычные изменяемые объекты), или лучше написать это? :

    String s = "hello";
    String backup_of_s = new String(s);
    s = "bye";

Другими словами, в чем разница (если есть) между этими двумя фрагментами?


РЕДАКТИРОВАТЬ - причина, по которой первый фрагмент безопасен:

Позвольте мне объяснить некоторые вещи немного подробнее, основываясь на уже предоставленных хороших ответах (которые были в основном сфокусированы на вопросе различий в производительности между двумя фрагментами):

Строки являются неизменяемыми в Java, что означает, что объект String не может быть изменен после его создания. Следовательно,

String s = "hello";создает новый экземпляр String и назначает его адрес s( sявляющийся ссылкой на экземпляр / объект)

String backup_of_s = s;создает новую переменную backup_of_sи инициализирует ее так, чтобы она ссылалась на объект, на который ссылается в данный момент s.

Примечание: неизменность строки гарантирует, что этот объект не будет изменен: наша резервная копия безопасна

Примечание 2. Механизм сборки мусора Java гарантирует, что этот объект не будет уничтожен, если на него ссылается хотя бы одна переменная ( backup_of_sв данном случае)

Наконец, s = "bye";создает другой экземпляр String (из-за неизменности, это единственный путь) и изменяет sпеременную так, чтобы она теперь ссылалась на новый объект.

Себастьен
источник

Ответы:

141

Поскольку строки неизменяемы, обе версии безопасны. Последний, однако, менее эффективен (он создает дополнительный объект и в некоторых случаях копирует данные персонажа).

Имея это в виду, первая версия должна быть предпочтительной.

NPE
источник
15
Неизменность не имеет к этому никакого отношения. Это просто, как работают ссылки на объекты. Я мог бы предоставить эквивалентный пример StringBuilder.
GriffeyDog
1
@BalusC, я не вижу, как new String () может создать что-либо в пуле String JVM. В него входят только строковые литералы и те, которые были переданы в пул через intern ().
Сниколас
3
@GriffeyDog: я читаю вопрос менее буквально. Я говорю о том, что можно безопасно давать ссылки на строковый объект, не опасаясь, что кто-то может изменить строку.
NPE
2
@GriffeyDog Я нахожу ваш комментарий очень вводящим в заблуждение: неизменность - это то, что делает первый фрагмент безопасным, почему вы говорите, что оно не имеет ничего общего с «этим»?
Себастьян
5
@Sebastien Все, что он делает, это переназначает ссылочную переменную sдля ссылки на другой объект ( String«пока»). Это не влияет на то, на что ссылается ссылочная переменная backup_of_s( String«привет»). Как я уже сказал, я мог бы предоставить эквивалентный пример с StringBuilders, который не является неизменным. Мой комментарий в основном касается оператора OP: на данный момент резервная переменная все еще содержит исходное значение «привет» (это из-за неизменности в String?).
GriffeyDog
22

Строки являются неизменяемыми объектами, поэтому вы можете скопировать их, просто скопировав ссылку на них, потому что объект, на который ссылаются, не может измениться ...

Таким образом, вы можете скопировать как в первом примере без проблем:

String s = "hello";
String backup_of_s = s;
s = "bye";
aleroot
источник
10

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

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

Дэвид Хеффернан
источник
0

Второй случай также неэффективен с точки зрения пула строк, вы должны явно вызвать intern () при возврате ссылки, чтобы сделать его интерном.

Амит Ядав
источник
-16
String str1="this is a string";
String str2=str1.clone();

Как насчет копирования, как это? Я думаю, что получить новую копию лучше, так что данные str1не будут затронуты, когда str2будут ссылаться и изменяться в дальнейшем действии.

Cqiao13
источник
3
Stringнеизменен. Строки клонирования не имеют особого смысла.
Владимир