Como devo copiar Strings em Java?

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

Nesse ponto, a variável de backup ainda contém o valor original "olá" (isso é devido à imutabilidade de String, certo?).

Mas é realmente seguro copiar Strings com esse método (o que obviamente não é seguro para copiar objetos mutáveis ​​regulares) ou é melhor escrever isso? :

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

Em outras palavras, qual é a diferença (se houver) entre esses dois trechos?


EDIT - o motivo pelo qual o primeiro trecho é seguro:

Deixe-me explicar as coisas com um pouco mais de detalhes, com base nas boas respostas já fornecidas (que foram essencialmente focadas na questão da diferença de desempenho entre os dois trechos):

Strings são imutáveis ​​em Java, o que significa que um objeto String não pode ser modificado após sua construção. Conseqüentemente,

String s = "hello";cria uma nova instância String e atribui seu endereço a s( ssendo uma referência à instância / objeto)

String backup_of_s = s;cria uma nova variável backup_of_se a inicializa para que faça referência ao objeto atualmente referenciado por s.

Nota: A imutabilidade da string garante que este objeto não seja modificado: nosso backup é seguro

Nota 2: O mecanismo de coleta de lixo Java garante que este objeto não será destruído desde que seja referenciado por pelo menos uma variável ( backup_of_sneste caso)

Por fim, s = "bye";cria outra instância String (por causa da imutabilidade, é a única maneira) e modifica a svariável para que agora faça referência ao novo objeto.

Sébastien
fonte

Respostas:

139

Como as strings são imutáveis, as duas versões são seguras. O último, no entanto, é menos eficiente (cria um objeto extra e, em alguns casos, copia os dados do personagem).

Com isso em mente, a primeira versão deve ser preferida.

NPE
fonte
15
A imutabilidade não tem nada a ver com isso. É simplesmente como as referências a objetos funcionam. Eu poderia fornecer um exemplo equivalente de StringBuilder.
GriffeyDog
1
@ BalusC, não vejo como o novo String () pode criar algo no pool de String da JVM. Somente literais de cordas e aqueles comprometidos com a piscina via intern () estão na piscina.
Snicolas 15/05
3
@GriffeyDog: Estou lendo a pergunta menos literalmente. O que estou dizendo é que é seguro fornecer referências a um objeto de string sem medo de que alguém possa modificá-la.
NPE
2
@GriffeyDog Acho seu comentário muito enganador: a imutabilidade é o que torna o primeiro trecho seguro, por que você diria que ele não tem nada a ver com "ele"?
Sébastien
5
@Sebastien Tudo o que está fazendo é reatribuir a variável de referência spara se referir a um objeto diferente (o String"tchau"). Isso não afeta a que a variável de referência backup_of_sestá se referindo (o String"olá"). Como eu disse, eu poderia fornecer um exemplo equivalente com StringBuilders, que não são imutáveis. Meu comentário é principalmente sobre a declaração de OPs: Neste ponto, a variável de backup ainda contém o valor original "olá" (isso é devido à imutabilidade de String, certo?).
GriffeyDog
22

Strings são objetos imutáveis, então você pode copiá-los apenas copiando a referência a eles, porque o objeto referenciado não pode mudar ...

Então você pode copiar como no seu primeiro exemplo sem nenhum problema:

String s = "hello";
String backup_of_s = s;
s = "bye";
aleroot
fonte
10

Sua segunda versão é menos eficiente porque cria um objeto de string extra quando simplesmente não há necessidade de fazê-lo.

Imutabilidade significa que sua primeira versão se comporta da maneira que você espera e, portanto, é a abordagem preferida.

David Heffernan
fonte
0

O segundo caso também é ineficiente em termos de pool de String, você deve chamar explicitamente intern () na referência de retorno para torná-lo interno.

Amit Yadav
fonte
-16
String str1="this is a string";
String str2=str1.clone();

Que tal uma cópia assim? Eu acho que obter uma nova cópia é melhor, para que os dados de str1não sejam afetados quando str2forem referenciados e modificados em outras ações.

Cqiao13
fonte
3
Stringé imutável. clonar Strings não faz muito sentido.
Vladimir