Comment copier des chaînes en Java?

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

À ce stade, la variable de sauvegarde contient toujours la valeur d'origine "bonjour" (c'est à cause de l'immuabilité de String, n'est-ce pas?).

Mais est-il vraiment sûr de copier des chaînes avec cette méthode (ce qui n'est bien sûr pas sûr de copier des objets mutables réguliers), ou est-il préférable d'écrire ceci? :

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

En d'autres termes, quelle est la différence (le cas échéant) entre ces deux extraits?


EDIT - la raison pour laquelle le premier extrait de code est sûr:

Permettez-moi juste d'expliquer les choses avec un peu plus de détails, en fonction des bonnes réponses déjà fournies (qui étaient essentiellement axées sur la question de la différence de performance entre les 2 extraits):

Les chaînes sont immuables en Java, ce qui signifie qu'un objet String ne peut pas être modifié après sa construction. Par conséquent,

String s = "hello";crée une nouvelle instance String et assigne son adresse à s( sétant une référence à l'instance / objet)

String backup_of_s = s;crée une nouvelle variable backup_of_set l'initialise afin qu'elle référence l'objet actuellement référencé par s.

Remarque: l'immuabilité des chaînes garantit que cet objet ne sera pas modifié: notre sauvegarde est sûre

Remarque 2: le mécanisme de récupération de place Java garantit que cet objet ne sera pas détruit tant qu'il est référencé par au moins une variable ( backup_of_sdans ce cas)

Enfin, s = "bye";crée une autre instance de String (en raison de l'immuabilité, c'est le seul moyen) et modifie la svariable afin qu'elle référence maintenant le nouvel objet.

Sébastien
la source

Réponses:

141

Les chaînes étant immuables, les deux versions sont sûres. Ce dernier, cependant, est moins efficace (il crée un objet supplémentaire et dans certains cas copie les données de caractères).

Dans cet esprit, la première version devrait être préférée.

NPE
la source
15
L'immuabilité n'a rien à voir avec cela. C'est simplement comment fonctionnent les références d'objets. Je pourrais fournir un exemple StringBuilder équivalent.
GriffeyDog
1
@BalusC, je ne vois pas comment new String () pourrait créer quoi que ce soit dans le pool String de la JVM. Seules les chaînes de caractères et celles engagées dans la piscine via intern () sont dans la piscine.
Snicolas
3
@GriffeyDog: Je lis la question moins littéralement. Ce que je dis, c'est qu'il est prudent de donner des références à un objet string sans craindre que quelqu'un puisse modifier la chaîne.
NPE
2
@GriffeyDog Je trouve votre commentaire très trompeur: l'immutabilité est ce qui rend le premier extrait de code sûr, pourquoi diriez-vous que cela n'a rien à voir avec "ça"?
Sébastien
5
@Sebastien Tout ce qu'il fait, c'est réaffecter la variable sde référence pour faire référence à un objet différent (le String"bye"). Cela n'affecte pas ce à quoi la variable de référence backup_of_sfait référence (le String"bonjour"). Comme je l'ai dit, je pourrais donner un exemple équivalent avec StringBuilders, qui ne sont pas immuables. Mon commentaire concerne principalement l'instruction OPs: à ce stade, la variable de sauvegarde contient toujours la valeur d'origine "bonjour" (c'est à cause de l'immuabilité de String, n'est-ce pas?).
GriffeyDog
22

Les chaînes sont des objets immuables , vous pouvez donc les copier simplement en y copiant la référence, car l'objet référencé ne peut pas changer ...

Vous pouvez donc copier comme dans votre premier exemple sans aucun problème:

String s = "hello";
String backup_of_s = s;
s = "bye";
aleroot
la source
10

Votre deuxième version est moins efficace car elle crée un objet chaîne supplémentaire lorsqu'il n'est tout simplement pas nécessaire de le faire.

L'immuabilité signifie que votre première version se comporte comme vous l'attendez et est donc l'approche à privilégier.

David Heffernan
la source
0

Le deuxième cas est également inefficace en termes de pool de chaînes, vous devez appeler explicitement intern () sur renvoi de référence pour le rendre interne.

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

Que diriez-vous de copier comme ça? Je pense qu'il est préférable d'obtenir une nouvelle copie, de sorte que les données de str1ne soient pas affectées lors de la str2référence et modifiées dans une action ultérieure.

Cqiao13
la source
3
Stringest immuable. cloner des chaînes n'a pas beaucoup de sens.
Vladimir