238 votes

Immutabilité des chaînes de caractères en Java

Prenons l'exemple suivant.

String str = new String();

str  = "Hello";
System.out.println(str);  //Prints Hello

str = "Help!";
System.out.println(str);  //Prints Help!

Or, en Java, les objets String sont immuables. Alors comment se fait-il que l'objet str peut se voir attribuer la valeur "Help !". N'est-ce pas en contradiction avec l'immuabilité des chaînes de caractères en Java ? Quelqu'un peut-il m'expliquer le concept exact d'immuabilité ?

Editar:

Ok, j'ai compris, mais j'ai une question complémentaire. Qu'en est-il du code suivant :

String str = "Mississippi"; 
System.out.println(str); // prints Mississippi 

str = str.replace("i", "!"); 
System.out.println(str); // prints M!ss!ss!pp! 

Cela signifie-t-il que deux objets sont créés à nouveau ("Mississippi" et "M!ss!ss!pp !") et que la référence str pointe vers un objet différent après replace() méthode ?

1 votes

Str est UNIQUEMENT une référence et non l'objet lui-même

1 votes

J'espère que cela vous aidera pushkarrajpujari.com/article/strings-in-java

349voto

gustafc Points 13552

str n'est pas un objet, c'est une référence à un objet. "Hello" y "Help!" sont deux distincts String objets. Ainsi, str Les points suivants une chaîne. Vous pouvez changer ce qu'il Les points suivants mais pas ce qu'elle points à .

Prenez ce code, par exemple :

String s1 = "Hello";
String s2 = s1;
// s1 and s2 now point at the same string - "Hello"

Maintenant, il n'y a rien 1 que nous pourrions faire pour s1 qui affecterait la valeur de s2 . Ils font référence au même objet - la chaîne de caractères "Hello" - mais cet objet est immuable et ne peut donc pas être modifié.

Si on fait quelque chose comme ça :

s1 = "Help!";
System.out.println(s2); // still prints "Hello"

Nous voyons ici la différence entre la mutation d'un objet et la modification d'une référence. s2 pointe toujours vers le même objet que celui que nous avions initialement défini. s1 pour pointer vers. Réglage de s1 a "Help!" ne modifie que le référence tandis que le String l'objet auquel il se référait à l'origine reste inchangé.

Si les chaînes étaient mutable, on pourrait faire quelque chose comme ça :

String s1 = "Hello";
String s2 = s1;
s1.setCharAt(1, 'a'); // Fictional method that sets character at a given pos in string
System.out.println(s2); // Prints "Hallo"

Editer pour répondre à l'édition de l'OP :

Si vous regardez le code source pour String.replace(char,char) (également disponible dans src.zip dans votre répertoire d'installation JDK -- un conseil de pro est de regarder là chaque fois que vous vous demandez comment quelque chose fonctionne vraiment) vous pouvez voir que ce qu'il fait est le suivant :

  • S'il y a une ou plusieurs occurrences de oldChar dans la chaîne de caractères actuelle, faire une copie de la chaîne de caractères actuelle où toutes les occurrences de oldChar sont remplacés par newChar .
  • Si le oldChar n'est pas présent dans la chaîne de caractères actuelle, retourne la chaîne de caractères actuelle.

Alors oui, "Mississippi".replace('i', '!') crée un nouveau String objet. Là encore, la règle suivante s'applique :

String s1 = "Mississippi";
String s2 = s1;
s1 = s1.replace('i', '!');
System.out.println(s1); // Prints "M!ss!ss!pp!"
System.out.println(s2); // Prints "Mississippi"
System.out.println(s1 == s2); // Prints "false" as s1 and s2 are two different objects

Votre devoir pour l'instant est de voir ce que le code ci-dessus fait si vous changez s1 = s1.replace('i', '!'); a s1 = s1.replace('Q', '!'); :)


1 En fait, il es possible de muter des chaînes de caractères (et d'autres objets immuables). Cela nécessite une réflexion et est très, très dangereux et ne devrait jamais être utilisé à moins que vous ne soyez réellement intéressé par la destruction du programme.

17 votes

+1 pour la méthode fictive, elle démontre la différence entre les objets immuables et les autres.

1 votes

Merci gustafc pour les exemples corrects et l'explication claire....Mais pouvez-vous juste répondre à la partie éditée dans la question s'il vous plaît ? Cela me permettra de mieux comprendre.

19 votes

Je n'ai jamais vu une réponse comme ça avant. On a discuté de chaque détail.

26voto

coobird Points 70356

L'objet qui str peuvent changer, mais les références réelles String les objets eux-mêmes ne le peuvent pas.

El String contenant la chaîne de caractères "Hello" y "Help!" ne peuvent pas modifier leurs valeurs, elles sont donc immuables.

L'immuabilité de String ne signifie pas que les références pointant vers l'objet ne peuvent pas changer.

Une façon d'empêcher la str pour éviter que la référence ne change, il faut la déclarer comme final :

final String STR = "Hello";

Maintenant, en essayant d'assigner un autre String a STR provoquera une erreur de compilation.

0 votes

Mais dans ce cas, l'objet String est 'str' qui contient d'abord la valeur 'Hello' puis se voit attribuer la nouvelle valeur 'Help!'. Que voulez-vous dire exactement par "Les objets String contenant les chaînes "Hello" et "Help !" ne peuvent pas changer de valeur, ils sont donc immuables" ? ???? Pardonnez-moi si c'est une question stupide. Mais je dois la clarifier...

2 votes

Avez-vous déjà essayé de programmer en C ? Lisez simplement l'introduction aux pointeurs et vous comprendrez parfaitement la réponse de Coobird.

0 votes

Vous voyez... C'est ce que je veux éviter... Je sais que vous êtes un grand programmeur... et j'essaie juste d'apprendre la Java... Alors si vous pouvez répondre correctement à ma question, répondez-y s'il vous plaît...

10voto

mlk Points 7270

Light_handle Je vous recommande de prendre connaissance de Cup Size -- une histoire de variables y Pass-by-Value s'il vous plaît (taille de la tasse suite) . Cela vous aidera beaucoup à lire les messages ci-dessus.

Vous les avez lus ? Oui. Bien.

String str = new String();

Cela crée une nouvelle " télécommande " appelée " str "et lui attribue la valeur new String() (ou "" ).

Par exemple, dans la mémoire, cela crée :

str --- > ""

str  = "Hello";

Cela change alors la télécommande " str "mais ne modifie pas la chaîne originale "" .

Par exemple, dans la mémoire, cela crée :

str -+   ""
     +-> "Hello"

str = "Help!";

Cela change alors la télécommande " str "mais ne modifie pas la chaîne originale "" ou l'objet que la télécommande pointe actuellement.

Par exemple, dans la mémoire, cela crée :

str -+   ""
     |   "Hello"
     +-> "Help!"

0 votes

Est-ce que "" et "Hello" sont collectés par les ordures ?

0 votes

@PrabinTimsina Ceci devrait vraiment être une nouvelle question. Il y est répondu : stackoverflow.com/questions/15324143/

6voto

daveb Points 24831

L'objet chaîne de caractères qui a été référencé pour la première fois par str n'a pas été modifié, tout ce que vous avez fait est de rendre str fait référence à un nouvel objet chaîne.

5voto

akf Points 23518

La chaîne ne changera pas, mais la référence à cette chaîne changera. Vous confondez l'immuabilité avec le concept de final champs. Si un champ est déclaré comme final une fois qu'il a été attribué, il ne peut plus être réattribué.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X