Prenons l'exemple suivant.
String str = new String();
str = "Hello";
System.out.println(str); //Prints Hello
str = "Help!";
System.out.println(str); //Prints Help!
Maintenant, en Java, les objets String sont immuables. Alors comment se fait-il que l'objet str
puisse se voir attribuer la valeur "Aide!". N'est-ce pas en contradiction avec l'immuabilité des chaînes en Java? Quelqu'un peut-il m'expliquer le concept exact d'immuabilité?
Éditer:
D'accord. Je comprends maintenant, mais une seule 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!
Est-ce à dire que deux objets sont à nouveau créés ("Mississippi" et "M! Ss! Ss! Pp!") Et que la référence str
pointe vers un objet différent après la replace()
méthode?
java
string
immutability
Light_handle
la source
la source
Réponses:
str
n'est pas un objet, c'est une référence à un objet."Hello"
et"Help!"
sont deuxString
objets distincts . Ainsi,str
pointe vers une chaîne. Vous pouvez modifier ce vers quoi il pointe , mais pas ce vers quoi il pointe .Prenez ce code, par exemple:
Maintenant, il n'y a rien 1 que nous pourrions faire pour
s1
cela affecter la valeurs2
. Ils se réfèrent au même objet - la chaîne"Hello"
- mais cet objet est immuable et ne peut donc pas être modifié.Si nous faisons quelque chose comme ça:
Ici, nous voyons la différence entre muter un objet et changer une référence.
s2
pointe toujours vers le même objet que celui que nous avions initialement définis1
. La définitions1
de"Help!"
ne modifie que la référence , tandis que l'String
objet auquel il faisait référence à l'origine reste inchangé.Si les chaînes étaient mutables, nous pourrions faire quelque chose comme ceci:
Modifier pour répondre à la modification de OP:
Si vous regardez le code source de String.replace (char, char) (également disponible dans src.zip dans votre répertoire d'installation JDK - une astuce pro consiste à y regarder chaque fois que vous vous demandez comment quelque chose fonctionne vraiment), vous pouvez voir que ce c'est le cas:
oldChar
dans la chaîne en cours, faites une copie de la chaîne en cours où toutes les occurrences deoldChar
sont remplacées parnewChar
.oldChar
n'est pas présent dans la chaîne actuelle, renvoyez la chaîne actuelle.Alors oui,
"Mississippi".replace('i', '!')
crée un nouvelString
objet. Encore une fois, ce qui suit tient:Votre devoir pour l'instant est de voir ce que fait le code ci-dessus si vous changez
s1 = s1.replace('i', '!');
ens1 = s1.replace('Q', '!');
:)1 En fait, il est possible de muter des chaînes (et d'autres objets immuables). Il nécessite une réflexion et est très, très dangereux et ne devrait jamais être utilisé à moins que vous ne souhaitiez réellement détruire le programme.
la source
L'objet
str
référencé peut changer, mais pas lesString
objets réels eux-mêmes.Les
String
objets contenant la chaîne"Hello"
et"Help!"
ne peuvent pas changer leurs valeurs, ils sont donc immuables.L'immuabilité des
String
objets ne signifie pas que les références pointant vers l'objet ne peuvent pas changer.Une façon d'empêcher la
str
référence de changer est de la déclarer commefinal
:Maintenant, en essayant d'assigner une autre
String
àSTR
provoquera une erreur de compilation.la source
str
n'est pas «l'objet», c'est une référence à l'objet. Si vous avezString str = "Hello";
suivi,String anotherReference = str;
vous n'avez pas 2 objets String, vous avez un objet (le littéral "Bonjour") et 2 références à lui (str
etanotherReference
).Light_handle Je vous recommande de lire la taille de la tasse - une histoire sur les variables et le passage par valeur s'il vous plaît (la taille de la tasse continue) . Cela vous sera très utile lors de la lecture des articles ci-dessus.
Les avez-vous lus? Oui. Bien.
Cela crée une nouvelle "télécommande" appelée "
str
" et la définit sur la valeurnew String()
(ou""
).par exemple en mémoire cela crée:
Cela modifie alors la télécommande "
str
" mais ne modifie pas la chaîne d'origine""
.par exemple en mémoire cela crée:
Cela modifie alors la télécommande "
str
" mais ne modifie pas la chaîne d'origine""
ou l'objet vers lequel la télécommande pointe actuellement.par exemple en mémoire cela crée:
la source
Permet de le briser en quelques parties
Cette déclaration crée une chaîne contenant bonjour et occupe de l'espace en mémoire, c'est-à-dire dans le pool de chaînes constant , et l'affecte à l'objet de référence s1
Cette instruction affecte la même chaîne bonjour à la nouvelle référence s2
Les deux références pointent vers la même chaîne, donc affichez la même valeur comme suit.
Bien que la chaîne soit immuable , l'affectation peut être possible, donc le s1 fera désormais référence à une nouvelle pile de valeurs .
Mais qu'en est-il de l' objet s2 qui pointe vers bonjour ce sera comme ça.
La chaîne étant immuable, la machine virtuelle Java ne nous permettra pas de modifier la chaîne s1 par sa méthode. Il créera tout nouvel objet String dans le pool comme suit.
Notez que si String devait être mutable, la sortie aurait été
Maintenant, vous pourriez être surpris de savoir pourquoi String a des méthodes telles que concat () à modifier. L'extrait suivant effacera votre confusion.
Ici, nous attribuons la valeur modifiée de la chaîne à la référence s1 .
C'est pourquoi Java a décidé que String était une classe finale. Sinon, n'importe qui peut modifier et changer la valeur de string. J'espère que cela vous aidera un peu.
la source
L'objet chaîne qui a été référencé pour la première fois
str
n'a pas été modifié, vous n'avez fait que fairestr
référence à un nouvel objet chaîne.la source
La chaîne ne changera pas, la référence y sera. Vous confondez l'immuabilité avec le concept de
final
champs. Si un champ est déclaré commefinal
, une fois qu'il a été attribué, il ne peut pas être réaffecté.la source
En ce qui concerne la partie remplacer de votre question, essayez ceci:
la source
Bien que java essaie de l'ignorer,
str
n'est rien de plus qu'un pointeur. Cela signifie que lorsque vous écrivez pour la première foisstr = "Hello";
, vous créez un objet quistr
pointe vers. Lorsque vous réaffectezstr
en écrivantstr = "Help!";
, un nouvel objet est créé et l'ancien"Hello"
objet est récupéré à chaque fois que java en a envie.la source
L'immuabilité implique que la valeur d'un objet instancié ne peut pas changer, vous ne pouvez jamais transformer "Bonjour" en "Aide!".
La variable str est une référence à un objet, lorsque vous affectez une nouvelle valeur à str, vous ne modifiez pas la valeur de l'objet qu'elle référence, vous faites référence à un autre objet.
la source
La classe de chaîne est immuable et vous ne pouvez pas modifier la valeur de l'objet immuable. Mais dans le cas de String, si vous modifiez la valeur de string, cela créera une nouvelle chaîne dans le pool de chaînes et votre référence de chaîne à cette valeur n'est pas la plus ancienne. de cette façon, la chaîne est immuable. Prenons votre exemple,
il créera une chaîne "Mississippi" et l'ajoutera au pool de chaînes alors maintenant str pointe vers le Mississippi.
Mais après l'opération ci-dessus, une autre chaîne sera créée "M! Ss! Ss! Pp!" et il sera ajouté au pool de chaînes. et maintenant str pointe sur M! ss! ss! pp !, pas sur le Mississippi.
de cette façon, lorsque vous modifierez la valeur de l'objet chaîne, il créera un objet supplémentaire et l'ajoutera au pool de chaînes.
Permet d'avoir un exemple de plus
cette ligne au-dessus de trois ajoutera trois objets de chaîne au pool de chaînes.
1) Bonjour
2) Monde
3) BonjourWorld
la source
Utilisation:
Si vous voyez ici, j'utilise la
concat
méthode pour changer la chaîne d'origine, c'est-à-dire "Nouvelle chaîne" avec une chaîne "Chaîne ajoutée", mais j'ai quand même obtenu la sortie comme précédemment, donc cela prouve que vous ne pouvez pas changer la référence de l'objet de la classe String, mais si vous faites cette chose par la classe StringBuilder, cela fonctionnera. Il est répertorié ci-dessous.la source
Comme l'a dit Linus Tolvards:
Regarde ça:
La sortie est
Souvenez-vous donc de deux choses:
la source
Pour ceux qui se demandent comment briser l'immuabilité des chaînes en Java ...
Code
Production
la source
La chaîne est immuable . Ce qui signifie que nous ne pouvons que changer la référence .
la source
En Java, les objets sont généralement accessibles par des références. Dans votre morceau de code str est une référence qui est d'abord affectée à "Bonjour" (un objet créé automatiquement ou récupéré à partir d' un pool constant ), puis vous avez affecté un autre objet "Aide!" à la même référence. Un point à noter est que la référence est la même et modifiée, mais les objets sont différents. Encore une chose dans votre code, vous avez accédé à trois objets,
L'appel de new String () crée un nouvel objet même s'il existe dans le pool de chaînes, il ne doit donc généralement pas être utilisé. Pour placer une chaîne créée à partir de new String () dans le pool de chaînes, vous pouvez essayer la
intern()
méthode.J'espère que ça aide.
la source
L'immuabilité, je peux dire, c'est que vous ne pouvez pas changer la chaîne elle-même. Supposons que vous ayez String x, dont la valeur est "abc". Maintenant, vous ne pouvez pas changer la chaîne, c'est-à-dire que vous ne pouvez pas changer de caractère / s dans "abc".
Si vous devez modifier des caractères dans la chaîne, vous pouvez utiliser un tableau de caractères et le muter ou utiliser StringBuilder.
Production:
la source
Ou vous pouvez essayer:
Cela montrera comment le code de hachage change.
la source
La chaîne est immuable signifie que vous ne pouvez pas modifier l'objet lui-même, mais vous pouvez modifier la référence à l'objet. Lorsque vous appelez a = "ty", vous changez en fait la référence de a à un nouvel objet créé par le littéral String "ty". Changer un objet signifie utiliser ses méthodes pour changer l'un de ses champs (ou les champs sont publics et non définitifs, afin qu'ils puissent être mis à jour de l'extérieur sans y accéder via des méthodes), par exemple:
Dans une classe immuable (déclarée comme finale, pour empêcher toute modification via l'héritage) (ses méthodes ne peuvent pas modifier ses champs, et les champs sont toujours privés et recommandés pour être définitifs), par exemple String, vous ne pouvez pas changer la chaîne actuelle mais vous peut retourner une nouvelle chaîne, c'est-à-dire:
la source
Ici, l'immuabilité signifie que l'instance peut pointer vers une autre référence, mais le contenu d'origine de la chaîne ne serait pas modifié à la référence d'origine. Je m'explique par le premier exemple que vous avez donné. La première chaîne pointe vers "Bonjour", c'est OK jusqu'à présent. La deuxième fois, il pointe vers "Aide!". Ici, str a commencé à pointer vers "Aide!" et la référence de la chaîne "Hello" est perdue et nous ne pouvons pas la récupérer.
En fait, lorsque str essaierait de modifier le contenu existant, une autre nouvelle chaîne sera générée et str commencera à pointer vers cette référence. Nous voyons donc que la chaîne à la référence d'origine n'est pas modifiée, mais que sa référence est sûre et que l'instance de l'objet a commencé à pointer vers une référence différente, donc l'immuabilité est conservée.
la source
Super tard pour la réponse, mais je voulais mettre un message concis de l'auteur de la classe String en Java
Il peut être dérivé de cette documentation que tout ce qui change de chaîne retourne un objet différent (qui pourrait être nouveau ou interné et ancien). L'astuce pas si subtile à ce sujet devrait provenir de la signature de la fonction. Pensez-y, «Pourquoi ont-ils fait une fonction sur un objet renvoyer un objet au lieu de statut?».
Aussi une autre source qui rend ce comportement explicite (à partir de la documentation de la fonction de remplacement)
Source: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char,%20char)
Source: JavaDoc de String.
la source
La méthode Object string - methods elle-même est conçue pour être "immuable". Cette action ne produit aucun changement: "letters.replace (" bbb "," aaa ");"
Mais l'attribution de données entraîne des modifications du contenu des chaînes:
// Le hashcode de la chaîne Object ne change pas.
la source
Si
HELLO
c'est votre chaîne, vous ne pouvez pas passerHELLO
àHILLO
. Cette propriété est appelée propriété d'immuabilité.Vous pouvez avoir plusieurs variables String pointeur pour pointer HELLO String.
Mais si BONJOUR est un tableau de caractères, vous pouvez changer BONJOUR en HILLO. Par exemple,
Les langages de programmation ont des variables de données immuables de sorte qu'ils peuvent être utilisés comme clés dans une paire clé / valeur.
la source
Je l'expliquerais avec un exemple simple
sur le tableau de caractères, nous pouvons effectuer des opérations comme imprimer uniquement les trois dernières lettres en utilisant l'itération du tableau; mais dans la chaîne, nous devons créer un nouvel objet chaîne et copier la sous-chaîne requise et son adresse sera dans le nouvel objet chaîne.
par exemple
donc s2 aura "hel";
la source
La chaîne en Java dans Immutable et Final signifie simplement qu'elle ne peut pas être changée ou modifiée:
Cas 1:
Cas 2:
la source
Parce que la chaîne est immuable, les modifications ne se produiront pas si vous n'affectez pas la valeur renvoyée de la fonction à la chaîne.
s = swap (s, n1, n2); alors la valeur de la chaîne s changera.
J'obtenais également la valeur inchangée lorsque j'écrivais le programme pour obtenir une chaîne de permutations (bien qu'il ne donne pas toutes les permutations mais c'est par exemple pour répondre à votre question)
Voici un exemple.
mais je n'obtenais pas les valeurs permutées de la chaîne à partir du code ci-dessus. J'ai donc attribué la valeur renvoyée de la fonction d'échange à la chaîne et obtenu des valeurs modifiées de la chaîne. après avoir attribué la valeur retournée, j'ai obtenu les valeurs permutées de la chaîne.
la source
Produira quelque chose comme ça
1419358369 1419358369
103056 65078777
Le but de l'objet immuable est que sa valeur ne doit pas être modifiée une fois attribuée. Il renverra un nouvel objet chaque fois que vous essayez de le modifier en fonction de l'implémentation. Remarque: Stringbuffer au lieu de chaîne peut être utilisé pour éviter cela.
Pour votre dernière question: u aura une référence et 2 chaînes dans le pool de chaînes. Sauf que la référence pointera vers m! Ss! Ss! Pp!
la source