Betrachten Sie das folgende Beispiel.
String str = new String();
str = "Hello";
System.out.println(str); //Prints Hello
str = "Help!";
System.out.println(str); //Prints Help!
In Java sind String-Objekte jetzt unveränderlich. Wie kommt es dann, dass dem Objekt str
der Wert "Hilfe!" Zugewiesen werden kann? Widerspricht dies nicht der Unveränderlichkeit von Strings in Java? Kann mir bitte jemand das genaue Konzept der Unveränderlichkeit erklären?
Bearbeiten:
OK. Ich verstehe es jetzt, aber nur eine Folgefrage. Was ist mit dem folgenden Code:
String str = "Mississippi";
System.out.println(str); // prints Mississippi
str = str.replace("i", "!");
System.out.println(str); // prints M!ss!ss!pp!
Bedeutet dies, dass zwei Objekte erneut erstellt werden ("Mississippi" und "M! Ss! Ss! Pp!") Und die Referenz str
nach der replace()
Methode auf ein anderes Objekt verweist ?
java
string
immutability
Lichtgriff
quelle
quelle
Antworten:
str
ist kein Objekt, es ist ein Verweis auf ein Objekt."Hello"
und"Help!"
sind zwei verschiedeneString
Objekte. Zeigt alsostr
auf eine Zeichenfolge. Sie können ändern, auf was es zeigt , aber nicht auf das, worauf es zeigt .Nehmen Sie diesen Code zum Beispiel:
Jetzt gibt es nichts 1 wir tun könnten , um
s1
die den Wert beeinflussen würdes2
. Sie beziehen sich auf dasselbe Objekt - die Zeichenfolge"Hello"
-, aber dieses Objekt ist unveränderlich und kann daher nicht geändert werden.Wenn wir so etwas machen:
Hier sehen wir den Unterschied zwischen dem Mutieren eines Objekts und dem Ändern einer Referenz.
s2
zeigt immer noch auf dasselbe Objekt, auf das wir ursprünglichs1
zeigen wollten. Wenn Sie festlegens1
, dass"Help!"
nur die Referenz geändertString
wird, bleibt das Objekt, auf das ursprünglich verwiesen wurde, unverändert.Wenn Strings waren wandelbar, könnten wir so etwas tun:
Bearbeiten, um auf die Bearbeitung von OP zu reagieren:
Wenn Sie sich den Quellcode für String.replace (char, char) ansehen (auch in src.zip in Ihrem JDK-Installationsverzeichnis verfügbar - ein Tipp ist, wenn Sie sich fragen, wie etwas wirklich funktioniert), können Sie sehen, was es ist das Folgende:
oldChar
die aktuelle Zeichenfolge ein oder mehrere Vorkommen von enthält , erstellen Sie eine Kopie der aktuellen Zeichenfolge, durch die alle Vorkommen vonoldChar
ersetzt werdennewChar
.oldChar
in der aktuellen Zeichenfolge nicht vorhanden ist, geben Sie die aktuelle Zeichenfolge zurück.Also ja,
"Mississippi".replace('i', '!')
erstellt ein neuesString
Objekt. Auch hier gilt:Ihre Hausaufgabe ist es, zu sehen, was der obige Code bewirkt, wenn Sie
s1 = s1.replace('i', '!');
zus1 = s1.replace('Q', '!');
:) wechseln.1 Eigentlich ist es ist möglich , zu mutieren Strings (und andere unveränderliche Objekte). Es erfordert Reflexion und ist sehr, sehr gefährlich und sollte niemals verwendet werden, es sei denn, Sie sind tatsächlich daran interessiert, das Programm zu zerstören.
quelle
Das Objekt, auf das
str
verwiesen wird, kann sich ändern, die tatsächlichenString
Objekte selbst jedoch nicht.Die
String
Objekte, die die Zeichenfolge enthalten"Hello"
und"Help!"
ihre Werte nicht ändern können, sind daher unveränderlich.Die Unveränderlichkeit von
String
Objekten bedeutet nicht, dass sich die Verweise auf das Objekt nicht ändern können.Eine Möglichkeit, die
str
Änderung der Referenz zu verhindern , besteht darin, sie wie folgt zu deklarierenfinal
:Wenn Sie nun versuchen, einen anderen zuzuweisen
String
,STR
wird ein Kompilierungsfehler verursacht.quelle
str
ist nicht das "Objekt", sondern eine Referenz auf das Objekt. Wenn SieString str = "Hello";
gefolgt sind, habenString anotherReference = str;
Sie keine 2 String-Objekte, Sie haben ein Objekt (das Literal "Hallo") und 2 Verweise darauf (str
undanotherReference
).Light_handle Ich empfehle Ihnen, die Cup-Größe zu lesen - eine Geschichte über Variablen und Pass-by-Value Please (Cup-Größe wird fortgesetzt) . Dies wird beim Lesen der obigen Beiträge sehr hilfreich sein.
Hast du sie gelesen? Ja. Gut.
Dadurch wird eine neue "Fernbedienung" mit dem Namen "
str
" erstellt und auf den Wertnew String()
(oder""
) gesetzt.zB im Gedächtnis schafft dies:
Dadurch wird die Fernbedienung "
str
" geändert, die ursprüngliche Zeichenfolge wird jedoch nicht geändert""
.zB im Gedächtnis schafft dies:
Dadurch wird die Fernbedienung "
str
" geändert , jedoch nicht die ursprüngliche Zeichenfolge""
oder das Objekt, auf das die Fernbedienung derzeit zeigt.zB im Gedächtnis schafft dies:
quelle
Lasst es uns in einige Teile zerlegen
Diese Anweisung erstellt eine Zeichenfolge, die Hallo enthält und Speicherplatz im Speicher belegt, dh im Konstanten Zeichenfolgenpool, und weist sie dem Referenzobjekt s1 zu
Diese Anweisung weist der neuen Referenz s2 dieselbe Zeichenfolge Hallo zu
Beide Referenzen verweisen auf dieselbe Zeichenfolge. Geben Sie daher denselben Wert wie folgt aus.
Obwohl String ist unveränderlich , kann Zuordnung möglich sein , so dass die s1 nun auf den neuen Wert bezieht Stapel .
Aber was ist mit dem s2- Objekt, das auf Hallo zeigt ? Es wird so sein, wie es ist.
Da String unveränderlich ist , können wir mit Java Virtual Machine den String s1 nicht nach seiner Methode ändern . Das neue String-Objekt im Pool wird wie folgt erstellt.
Beachten Sie, wenn String veränderlich wäre, wäre die Ausgabe gewesen
Jetzt werden Sie überrascht sein, warum String Methoden wie concat () zum Ändern hat. Das Folgen des Snippets wird Ihre Verwirrung beseitigen.
Hier weisen wir der s1- Referenz den geänderten Wert des Strings zurück .
Aus diesem Grund hat Java String als letzte Klasse festgelegt. Andernfalls kann jeder den Wert des Strings ändern. Hoffe das wird ein bisschen helfen.
quelle
Das Zeichenfolgenobjekt, auf das zuerst verwiesen wurde,
str
wurde nicht geändert. Sie habenstr
lediglich auf ein neues Zeichenfolgenobjekt verwiesen.quelle
Der String ändert sich nicht, der Verweis darauf ändert sich. Sie verwechseln Unveränderlichkeit mit dem Konzept der
final
Felder. Wenn ein Feld nachfinal
seiner Zuweisung als deklariert wird , kann es nicht neu zugewiesen werden.quelle
Versuchen Sie Folgendes, um den Ersatzteil Ihrer Frage zu ersetzen:
quelle
Obwohl Java versucht, es zu ignorieren,
str
ist es nichts weiter als ein Zeiger. Dies bedeutet, dass Sie beim ersten Schreibenstr = "Hello";
ein Objekt erstellen, auf dasstr
verweist. Wenn Siestr
durch Schreibenstr = "Help!";
eine Neuzuweisung vornehmen , wird ein neues Objekt erstellt und das alte"Hello"
Objekt wird mit Müll gesammelt, wenn Java dies wünscht.quelle
Unveränderlichkeit bedeutet, dass sich der Wert eines instanziierten Objekts nicht ändern kann. Sie können "Hallo" niemals in "Hilfe!" Verwandeln.
Die Variable str ist eine Referenz auf ein Objekt. Wenn Sie str einen neuen Wert zuweisen, ändern Sie nicht den Wert des Objekts, auf das sie verweist, sondern auf ein anderes Objekt.
quelle
Die Zeichenfolgenklasse ist unveränderlich, und Sie können den Wert des unveränderlichen Objekts nicht ändern. Wenn Sie jedoch im Fall von String den Wert des Strings ändern, wird ein neuer String im String-Pool erstellt, und Ihr String-Verweis auf diesen Wert ist nicht der ältere. Auf diese Weise ist die Zeichenfolge unveränderlich. Nehmen wir Ihr Beispiel,
Es wird eine Zeichenfolge "Mississippi" erstellt und zum Zeichenfolgenpool hinzugefügt, sodass str jetzt auf Mississippi zeigt.
Nach der obigen Operation wird jedoch eine weitere Zeichenfolge "M! Ss! Ss! Pp!" Erstellt. und es wird zum String-Pool hinzugefügt. und jetzt zeigt str auf M! ss! ss! pp!, nicht auf Mississippi.
Auf diese Weise wird beim Ändern des Werts des Zeichenfolgenobjekts ein weiteres Objekt erstellt und dem Zeichenfolgenpool hinzugefügt.
Lassen Sie uns noch ein Beispiel haben
Diese obige drei Zeilen fügen dem String-Pool drei String-Objekte hinzu.
1) Hallo
2) Welt
3) Hallo Welt
quelle
Verwenden:
Wenn Sie hier sehen, verwende ich die
concat
Methode, um die ursprüngliche Zeichenfolge, dh "Neue Zeichenfolge", durch eine Zeichenfolge "Hinzugefügte Zeichenfolge" zu ändern, aber ich habe die Ausgabe wie zuvor erhalten, sodass bewiesen wird, dass Sie die Referenz des Objekts nicht ändern können der String-Klasse, aber wenn Sie dies mit der StringBuilder-Klasse tun, wird es funktionieren. Es ist unten aufgeführt.quelle
Wie Linus Tolvards sagte:
Schau dir das an:
Die Ausgabe ist
Denken Sie also an zwei Dinge:
quelle
Für diejenigen, die sich fragen, wie man die Unveränderlichkeit von Strings in Java bricht ...
Code
Ausgabe
quelle
String ist unveränderlich . Das heißt, wir können nur die Referenz ändern .
quelle
In Java wird auf Objekte im Allgemeinen über Referenzen zugegriffen. In Ihrem Code befindet sich str eine Referenz, die zuerst "Hallo" zugewiesen wird (ein automatisch erstelltes Objekt oder aus einem konstanten Pool abgerufen ) und dann ein anderes Objekt "Hilfe!" zu derselben Referenz. Ein zu beachtender Punkt ist, dass die Referenz dieselbe und modifizierte ist, die Objekte jedoch unterschiedlich sind. Eine weitere Sache in Ihrem Code, auf die Sie zugegriffen haben, sind drei Objekte:
Durch Aufrufen von new String () wird ein neues Objekt erstellt, auch wenn es im Zeichenfolgenpool vorhanden ist. Daher sollte es im Allgemeinen nicht verwendet werden. Um eine aus new String () erstellte Zeichenfolge in den Zeichenfolgenpool einzufügen, können Sie die
intern()
Methode ausprobieren .Ich hoffe das hilft.
quelle
Unveränderlichkeit kann ich sagen, dass Sie den String selbst nicht ändern können. Angenommen, Sie haben String x, dessen Wert "abc" ist. Jetzt können Sie den String nicht mehr ändern, dh Sie können keine Zeichen in "abc" ändern.
Wenn Sie Zeichen in der Zeichenfolge ändern müssen, können Sie ein Zeichenarray verwenden und es mutieren oder StringBuilder verwenden.
Ausgabe:
quelle
Oder Sie können versuchen:
Dies zeigt, wie sich der Hashcode ändert.
quelle
Zeichenfolge ist unveränderlich bedeutet, dass Sie das Objekt selbst nicht ändern können, aber den Verweis auf das Objekt ändern können. Wenn Sie a = "ty" aufgerufen haben, ändern Sie tatsächlich die Referenz von a auf ein neues Objekt, das durch das String-Literal "ty" erstellt wurde. Das Ändern eines Objekts bedeutet, seine Methoden zum Ändern eines seiner Felder zu verwenden (oder die Felder sind öffentlich und nicht endgültig, sodass sie von außen aktualisiert werden können, ohne über Methoden auf sie zuzugreifen), zum Beispiel:
In einer unveränderlichen Klasse (als final deklariert, um Änderungen durch Vererbung zu verhindern) (ihre Methoden können ihre Felder nicht ändern, und auch die Felder sind immer privat und werden als final empfohlen), z. B. String, können Sie den aktuellen String nur Sie selbst ändern kann einen neuen String zurückgeben, dh:
quelle
Unveränderlichkeit bedeutet hier, dass die Instanz auf eine andere Referenz verweisen kann, der ursprüngliche Inhalt der Zeichenfolge jedoch bei der ursprünglichen Referenz nicht geändert wird. Lassen Sie mich anhand des ersten von Ihnen gegebenen Beispiels erklären. Die erste Str zeigt auf "Hallo", bis dahin ist es in Ordnung. Zum zweiten Mal zeigt es auf "Hilfe!". Hier zeigte str auf "Hilfe!" und die Referenz von "Hallo" Zeichenfolge geht verloren und wir können das nicht zurückbekommen.
Wenn str versucht, den vorhandenen Inhalt zu ändern, wird eine weitere neue Zeichenfolge generiert, und str zeigt auf diese Referenz. Wir sehen also, dass die Zeichenfolge an der ursprünglichen Referenz nicht geändert wird, aber an ihrer Referenz sicher ist und die Instanz des Objekts auf eine andere Referenz zeigt, sodass die Unveränderlichkeit erhalten bleibt.
quelle
Super spät zur Antwort, wollte aber eine kurze Nachricht vom Autor der String-Klasse in Java einfügen
Aus dieser Dokumentation kann abgeleitet werden, dass alles, was die Zeichenfolge ändert, ein anderes Objekt zurückgibt (das neu oder intern und alt sein kann). Der nicht so subtile Hinweis dazu sollte aus der Funktionssignatur stammen. Denken Sie darüber nach: "Warum haben sie eine Funktion für ein Objekt dazu gebracht, ein Objekt anstelle des Status zurückzugeben?"
Auch eine weitere Quelle, die dieses Verhalten explizit macht (Aus der Dokumentation der Ersetzungsfunktion)
Quelle: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char,%20char)
Quelle: JavaDoc von String.
quelle
Die Object string - Methoden selbst werden als "unveränderlich" festgelegt. Diese Aktion bewirkt keine Änderungen: "letters.replace (" bbb "," aaa ");"
Das Zuweisen von Daten führt jedoch dazu, dass sich Änderungen am Inhalt der Zeichenfolgen ändern:
// Der Hashcode des String-Objekts ändert sich nicht.
quelle
Wenn
HELLO
Ihr String ist , dann können Sie nicht ändernHELLO
zuHILLO
. Diese Eigenschaft wird als Unveränderlichkeitseigenschaft bezeichnet.Sie können mehrere Zeiger-String-Variablen verwenden, um auf HELLO String zu zeigen.
Wenn HELLO jedoch char Array ist, können Sie HELLO in HILLO ändern. Z.B,
Programmiersprachen haben unveränderliche Datenvariablen, so dass sie als Schlüssel im Schlüssel-Wert-Paar verwendet werden können.
quelle
Ich würde es mit einem einfachen Beispiel erklären
Auf Zeichenarrays können wir Operationen ausführen, z. B. nur die letzten drei Buchstaben drucken, indem wir das Array iterieren. Aber in String müssen wir ein neues String-Objekt erstellen und den erforderlichen Teilstring kopieren. Die Adresse befindet sich in einem neuen String-Objekt.
z.B
also wird s2 "hel" haben;
quelle
String in Java in Immutable und Final bedeutet nur, dass er nicht geändert oder modifiziert werden kann:
Fall 1:
Fall 2:
quelle
Da String unveränderlich ist, treten keine Änderungen auf, wenn Sie den zurückgegebenen Wert der Funktion nicht dem String zuweisen. Weisen Sie in Ihrer Frage den Wert der zurückgegebenen Swap-Funktion s zu.
s = swap (s, n1, n2), dann ändert sich der Wert der Zeichenfolge s.
Ich habe auch den unveränderten Wert erhalten, als ich das Programm geschrieben habe, um eine Permutationszeichenfolge zu erhalten (obwohl es nicht alle Permutationen gibt, aber dies ist zum Beispiel, um Ihre Frage zu beantworten).
Hier ist ein Beispiel.
Aber ich habe die permutierten Werte der Zeichenfolge nicht aus dem obigen Code erhalten. Also habe ich der Zeichenfolge den zurückgegebenen Wert der Swap-Funktion zugewiesen und die Werte der Zeichenfolge geändert. Nach dem Zuweisen des zurückgegebenen Wertes erhielt ich die permutierten Werte der Zeichenfolge.
quelle
Wird so etwas produzieren
1419358369 1419358369
103056 65078777
Zweck des unveränderlichen Objekts ist, dass sein Wert nach seiner Zuweisung nicht geändert wird. Jedes Mal, wenn Sie versuchen, es basierend auf der Implementierung zu ändern, wird ein neues Objekt zurückgegeben. Hinweis: Stringbuffer anstelle von String kann verwendet werden, um dies zu vermeiden.
Zu Ihrer letzten Frage :: u hat eine Referenz und 2 Zeichenfolgen im Zeichenfolgenpool. Außer die Referenz zeigt auf m! Ss! Ss! Pp!
quelle