Dies könnte die dümmste Frage sein, die jemals gestellt wurde, aber ich denke, dass es für einen Java-Neuling ziemlich verwirrend ist.
- Kann jemand klarstellen, was unter unveränderlich zu verstehen ist ?
- Warum ist ein
String
unveränderlicher? - Was sind die Vor- und Nachteile der unveränderlichen Objekte?
- Warum sollte ein veränderliches Objekt wie
StringBuilder
String gegenüber String bevorzugt werden und umgekehrt?
Ein schönes Beispiel (in Java) wird sehr geschätzt.
java
string
immutability
ashokgelal
quelle
quelle
Antworten:
Unveränderlich bedeutet, dass diese Instanz nicht geändert werden kann, sobald der Konstruktor für ein Objekt die Ausführung abgeschlossen hat.
Dies ist nützlich, da Sie Verweise auf das Objekt weitergeben können, ohne befürchten zu müssen, dass jemand anderes seinen Inhalt ändert. Insbesondere beim Umgang mit Parallelität treten bei Objekten, die sich nie ändern, keine Sperrprobleme auf
z.B
Foo
Sie müssen sich keine Sorgen machen, dass der AufrufergetValue()
den Text in der Zeichenfolge ändern könnte.Wenn Sie sich eine ähnliche Klasse vorstellen
Foo
, jedoch mit einemStringBuilder
alsString
Mitglied, können Sie sehen, dass ein AufrufergetValue()
dasStringBuilder
Attribut einerFoo
Instanz ändern kann .Achten Sie auch auf die verschiedenen Arten der Unveränderlichkeit: Eric Lippert hat einen Blog-Artikel darüber geschrieben. Grundsätzlich können Sie Objekte haben, deren Schnittstelle unveränderlich ist, aber hinter den Kulissen den tatsächlichen veränderlichen privaten Status (und daher nicht sicher zwischen Threads geteilt werden können).
quelle
Ein unveränderliches Objekt ist ein Objekt, bei dem die internen Felder (oder zumindest alle internen Felder, die sich auf das externe Verhalten auswirken) nicht geändert werden können.
Unveränderliche Saiten bieten viele Vorteile:
Leistung: Führen Sie die folgenden Schritte aus:
Das zugrunde liegende C für die Methode substring () ist wahrscheinlich ungefähr so:
Beachten Sie, dass keines der Zeichen kopiert werden muss! Wenn das String-Objekt veränderbar wäre (die Zeichen könnten sich später ändern), müssten Sie alle Zeichen kopieren, andernfalls würden Änderungen an Zeichen in der Teilzeichenfolge später in der anderen Zeichenfolge wiedergegeben.
Parallelität: Wenn die interne Struktur eines unveränderlichen Objekts gültig ist, ist sie immer gültig. Es besteht keine Möglichkeit, dass verschiedene Threads einen ungültigen Status innerhalb dieses Objekts erstellen. Daher sind unveränderliche Objekte threadsicher .
Speicherbereinigung: Für den Speicherbereiniger ist es viel einfacher, logische Entscheidungen über unveränderliche Objekte zu treffen.
Die Unveränderlichkeit hat jedoch auch Nachteile:
Leistung: Warten Sie, ich dachte, Sie sagten, Leistung sei ein Vorteil der Unveränderlichkeit! Nun, manchmal, aber nicht immer. Nehmen Sie den folgenden Code:
Die beiden Zeilen ersetzen das vierte Zeichen durch den Buchstaben "a". Der zweite Code ist nicht nur besser lesbar, sondern auch schneller. Schauen Sie sich an, wie Sie den zugrunde liegenden Code für foo erstellen müssten. Die Teilzeichenfolgen sind einfach, aber jetzt, da sich bereits ein Zeichen im fünften Feld befindet und etwas anderes möglicherweise auf foo verweist, können Sie es nicht einfach ändern. Sie müssen die gesamte Zeichenfolge kopieren (natürlich wird ein Teil dieser Funktionalität in Funktionen im realen zugrunde liegenden C abstrahiert, aber hier geht es darum, den Code anzuzeigen, der an einer Stelle ausgeführt wird).
Beachten Sie, dass die Verkettung zweimal aufgerufen wird, was bedeutet, dass die gesamte Zeichenfolge durchlaufen werden muss! Vergleichen Sie dies mit dem C-Code für die
bar
Operation:Die veränderbare String-Operation ist offensichtlich viel schneller.
Fazit: In den meisten Fällen möchten Sie eine unveränderliche Zeichenfolge. Wenn Sie jedoch viel anhängen und in eine Zeichenfolge einfügen müssen, benötigen Sie die Veränderbarkeit für die Geschwindigkeit. Wenn Sie die Vorteile der Parallelitätssicherheit und der Speicherbereinigung nutzen möchten, müssen Sie Ihre veränderlichen Objekte für eine Methode lokal halten:
Da es sich bei dem
mutable
Objekt um eine lokale Referenz handelt, müssen Sie sich keine Gedanken über die Sicherheit der Parallelität machen (nur ein Thread berührt es jemals). Und da es nirgendwo anders referenziert wird, wird es nur auf dem Stapel zugewiesen, sodass die Zuordnung aufgehoben wird, sobald der Funktionsaufruf abgeschlossen ist (Sie müssen sich nicht um die Speicherbereinigung kümmern). Und Sie erhalten alle Leistungsvorteile von Veränderlichkeit und Unveränderlichkeit.quelle
Passing pointers because Java is pass-by-reference
Ist Java nicht "Pass-by-Value"?Tatsächlich ist String nicht unveränderlich, wenn Sie die oben vorgeschlagene Wikipedia-Definition verwenden.
Der Status des Strings ändert die Postkonstruktion. Schauen Sie sich die Hashcode () -Methode an. String speichert den Hashcode-Wert in einem lokalen Feld zwischen, berechnet ihn jedoch erst beim ersten Aufruf von Hashcode (). Diese verzögerte Auswertung von Hashcode bringt String an eine interessante Position als unveränderliches Objekt, dessen Status sich ändert, aber es kann nicht beobachtet werden, dass es sich ohne Verwendung von Reflexion geändert hat.
Vielleicht sollte die Definition von unveränderlich ein Objekt sein, von dem nicht beobachtet werden kann, dass es sich geändert hat.
Wenn sich der Status eines unveränderlichen Objekts ändert, nachdem es erstellt wurde, aber niemand es sehen kann (ohne Reflexion), ist das Objekt dann noch unveränderlich?
quelle
Unveränderliche Objekte sind Objekte, die nicht programmgesteuert geändert werden können. Sie eignen sich besonders für Umgebungen mit mehreren Threads oder andere Umgebungen, in denen mehr als ein Prozess die Werte in einem Objekt ändern (mutieren) kann.
Um dies zu verdeutlichen, ist StringBuilder tatsächlich ein veränderliches Objekt, kein unveränderliches. Ein regulärer Java-String ist unveränderlich (dh, sobald er erstellt wurde, können Sie den zugrunde liegenden String nicht mehr ändern, ohne das Objekt zu ändern).
Angenommen, ich habe eine Klasse namens ColoredString mit einem String-Wert und einer String-Farbe:
In diesem Beispiel wird der ColoredString als veränderbar bezeichnet, da Sie eine seiner Schlüsseleigenschaften ändern (mutieren) können, ohne eine neue ColoredString-Klasse zu erstellen. Der Grund, warum dies möglicherweise schlecht ist, ist beispielsweise, dass Sie eine GUI-Anwendung mit mehreren Threads haben und ColoredStrings verwenden, um Daten in das Fenster zu drucken. Wenn Sie eine Instanz von ColoredString haben, die als erstellt wurde
Dann würden Sie erwarten, dass die Zeichenfolge immer "Blau" ist. Wenn jedoch ein anderer Thread diese Instanz erhalten und aufgerufen hat
Sie würden plötzlich und wahrscheinlich unerwartet jetzt eine "rote" Saite haben, wenn Sie eine "blaue" wollten. Aus diesem Grund werden unveränderliche Objekte fast immer bevorzugt, wenn Instanzen von Objekten weitergegeben werden. Wenn Sie einen Fall haben, in dem veränderbare Objekte wirklich notwendig sind, schützen Sie das Objekt normalerweise, indem Sie nur Kopien aus Ihrem spezifischen Kontrollbereich verteilen.
Zusammenfassend ist java.lang.String in Java ein unveränderliches Objekt (es kann nach seiner Erstellung nicht mehr geändert werden) und java.lang.StringBuilder ist ein veränderliches Objekt, da es geändert werden kann, ohne eine neue Instanz zu erstellen.
quelle
String s1 = "Alter String";
String s2 = s1;
s1 = "Neuer String";
quelle
"unveränderlich" bedeutet, dass Sie den Wert nicht ändern können. Wenn Sie eine Instanz der String-Klasse haben, erstellt jede von Ihnen aufgerufene Methode, die den Wert zu ändern scheint, tatsächlich einen weiteren String.
Um Änderungen beizubehalten, sollten Sie Folgendes tun: foo = foo.sustring (3);
Unveränderlich gegen veränderlich kann lustig sein, wenn Sie mit Sammlungen arbeiten. Überlegen Sie, was passieren wird, wenn Sie ein veränderliches Objekt als Schlüssel für die Karte verwenden und dann den Wert ändern (Tipp: Denken Sie an
equals
undhashCode
).quelle
java.time
Es mag etwas spät sein, aber um zu verstehen, was ein unveränderliches Objekt ist, betrachten Sie das folgende Beispiel aus der neuen Java 8-API für Datum und Uhrzeit ( java.time ). Wie Sie wahrscheinlich wissen, sind alle Datumsobjekte aus Java 8 im folgenden Beispiel unveränderlich
Ausgabe:
Dies gibt das gleiche Jahr wie das ursprüngliche Datum aus, da
plusYears(2)
ein neues Objekt zurückgegeben wird, sodass das alte Datum unverändert bleibt, da es sich um ein unveränderliches Objekt handelt. Einmal erstellt, können Sie es nicht weiter ändern und die Datumsvariable zeigt weiterhin darauf.Dieses Codebeispiel sollte also das neue Objekt erfassen und verwenden, das von diesem Aufruf an instanziiert und zurückgegeben wird
plusYears
.quelle
Die Erklärung von SCJP Sun Certified Programmer für Java 5 Study Guide gefällt mir sehr gut .
quelle
Unveränderliche Objekte können ihren Status nach ihrer Erstellung nicht mehr ändern.
Es gibt drei Hauptgründe, unveränderliche Objekte zu verwenden, wann immer Sie können. All dies trägt dazu bei, die Anzahl der Fehler zu verringern, die Sie in Ihren Code einführen:
Es gibt auch einige andere Optimierungen, die Sie möglicherweise im Code vornehmen können, wenn Sie wissen, dass der Status eines Objekts unveränderlich ist - beispielsweise das Zwischenspeichern des berechneten Hashs -, aber dies sind Optimierungen und daher bei weitem nicht so interessant.
quelle
Eine Bedeutung hängt damit zusammen, wie der Wert auf dem Computer gespeichert wird. Für eine .Net-Zeichenfolge bedeutet dies beispielsweise, dass die Zeichenfolge im Speicher nicht geändert werden kann. Wenn Sie glauben, dass Sie sie ändern, erstellen Sie tatsächlich eine neue Zeichenfolge im Speicher und Zeigen der vorhandenen Variablen (die nur ein Zeiger auf die tatsächliche Sammlung von Zeichen an einer anderen Stelle ist) auf die neue Zeichenfolge.
quelle
s1="Hi"
: Ein Objekts1
wurde mit dem Wert "Hi" erstellt.s2=s1
: Ein Objekts2
wird mit Bezug auf das s1-Objekt erstellt.s1="Bye"
:s1
Der Wert des vorherigen Objekts ändert sich nicht, das1
der String-Typ und der String-Typ ein unveränderlicher Typ sind. Stattdessen erstellt der Compiler ein neues String-Objekt mit dem Wert "Bye" unds1
verweist darauf. Wenn wir hier dens2
Wert drucken , ist das Ergebnis "Hi", nicht "Bye", das2
auf das vorheriges1
Objekt verwiesen wird, das den Wert "Hi" hatte.quelle
Unveränderlich bedeutet, dass sich nach dem Erstellen des Objekts keines seiner Mitglieder ändert.
String
ist unveränderlich, da Sie seinen Inhalt nicht ändern können. Zum Beispiel:Im obigen Code hat sich die Zeichenfolge s1 nicht geändert, ein anderes Objekt (
s2
) wurde mit erstellts1
.quelle
Unveränderlich bedeutet einfach unveränderlich oder nicht veränderbar. Sobald ein Zeichenfolgenobjekt erstellt wurde, können seine Daten oder sein Status nicht mehr geändert werden
Betrachten Sie das folgende Beispiel:
Lassen Sie uns eine Vorstellung von dem folgenden Diagramm bekommen.
In diesem Diagramm sehen Sie ein neues Objekt, das als "Future World" erstellt wurde. Aber nicht "Zukunft" ändern.
Because String is immutable
.s
, beziehen sich immer noch auf "Zukunft". Wenn Sie "Future World" nennen müssen,Warum sind String-Objekte in Java unveränderlich?
quelle
Einmal instanziiert, kann nicht mehr geändert werden. Stellen Sie sich eine Klasse vor, deren Instanz möglicherweise als Schlüssel für eine Hashtabelle oder ähnliches verwendet wird. Lesen Sie die Best Practices für Java.
quelle
Unveränderliche Objekte
Ein Objekt gilt als unveränderlich, wenn sich sein Zustand nach seiner Erstellung nicht ändern kann. Maximale Abhängigkeit von unveränderlichen Objekten wird allgemein als solide Strategie zur Erstellung von einfachem, zuverlässigem Code akzeptiert.
Unveränderliche Objekte sind besonders nützlich bei gleichzeitigen Anwendungen. Da sie den Status nicht ändern können, können sie nicht durch Thread-Interferenzen beschädigt oder in einem inkonsistenten Status beobachtet werden.
Programmierer zögern oft, unveränderliche Objekte zu verwenden, da sie sich Sorgen über die Kosten für die Erstellung eines neuen Objekts machen, anstatt ein vorhandenes Objekt zu aktualisieren. Die Auswirkungen der Objekterstellung werden häufig überschätzt und können durch einige der mit unveränderlichen Objekten verbundenen Effizienzvorteile ausgeglichen werden. Dazu gehören ein geringerer Overhead aufgrund der Speicherbereinigung und die Beseitigung von Code, der zum Schutz veränderlicher Objekte vor Beschädigung erforderlich ist.
Die folgenden Unterabschnitte nehmen eine Klasse, deren Instanzen veränderbar sind, und leiten daraus eine Klasse mit unveränderlichen Instanzen ab. Dabei geben sie allgemeine Regeln für diese Art der Konvertierung an und demonstrieren einige der Vorteile unveränderlicher Objekte.
Quelle
quelle
Da die akzeptierte Antwort nicht alle Fragen beantwortet. Ich bin gezwungen, nach 11 Jahren und 6 Monaten eine Antwort zu geben.
Ich hoffe, Sie meinten ein unveränderliches Objekt (weil wir über unveränderliche Referenzen nachdenken konnten ).
Ein Objekt ist unveränderlich : Wenn es einmal erstellt wurde, stellen sie immer denselben Wert dar (es gibt keine Methode, die den Wert ändert).
Beachten Sie die obige Definition, die durch einen Blick in den Quellcode von Sting.java überprüft werden kann.
sicherer vor Insekten.
leichter zu verstehen.
und mehr bereit für Veränderungen.
Eingrenzen der Frage Warum brauchen wir den veränderlichen StringBuilder für die Programmierung? Es wird häufig verwendet, um eine große Anzahl von Zeichenfolgen wie folgt miteinander zu verknüpfen:
Bei Verwendung unveränderlicher Zeichenfolgen werden viele temporäre Kopien erstellt - die erste Nummer der Zeichenfolge ("0") wird im Verlauf des Aufbaus der endgültigen Zeichenfolge tatsächlich n-mal kopiert, die zweite Nummer wird n-1-mal kopiert und so weiter auf. Es kostet tatsächlich O (n2) Zeit, nur das ganze Kopieren durchzuführen, obwohl wir nur n Elemente verkettet haben.
StringBuilder wurde entwickelt, um dieses Kopieren zu minimieren. Es verwendet eine einfache, aber clevere interne Datenstruktur, um zu vermeiden, dass bis zum Ende kopiert wird, wenn Sie mit einem toString () -Aufruf nach dem endgültigen String fragen:
Eine gute Leistung ist ein Grund, warum wir veränderbare Objekte verwenden. Ein weiterer Grund ist die bequeme Freigabe: Zwei Teile Ihres Programms können bequemer kommunizieren, indem Sie eine gemeinsame veränderbare Datenstruktur gemeinsam nutzen.
Weitere finden Sie hier: https://web.mit.edu/6.005/www/fa15/classes/09-immutability/#useful_immutable_types
quelle
Ein unveränderliches Objekt können Sie nach dem Erstellen nicht mehr ändern. Ein typisches Beispiel sind String-Literale.
Die AD-Programmiersprache, die immer beliebter wird, hat den Begriff "Unveränderlichkeit" durch das Schlüsselwort "invariant". Lesen Sie den Artikel von Dr.Dobb darüber - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29 . Es erklärt das Problem perfekt.
quelle