Ich wurde in einem Interview gefragt, warum String unveränderlich ist
Ich antwortete so:
Wenn wir einen String in Java wie
String s1="hello";
dann erstellen, wird ein Objekt im String-Pool erstellt (Hallo) und s1 zeigt auf Hallo . Wenn wir dies erneut tun,String s2="hello";
wird kein anderes Objekt erstellt, aber s2 zeigt darauf,hello
weil JVM zuerst prüft Wenn dasselbe Objekt im Zeichenfolgenpool vorhanden ist oder nicht. Wenn es nicht vorhanden ist, wird nur ein neues Objekt erstellt, andernfalls nicht.
Wenn nun angenommen wird, dass Java eine veränderbare Zeichenfolge zulässt , ist der Wert von s2 ebenfalls, wenn wir s1 in ändernhello world
hello world
, so Java - String unveränderlich ist.
Kann mir bitte jemand sagen, ob meine Antwort richtig oder falsch ist ?
std::string
ist veränderlich, aber sie haben auch einen String-Pool (genauer gesagt, einen Zeichen-Array-Pool).Antworten:
String
ist aus mehreren Gründen unveränderlich, hier eine Zusammenfassung:String
in Netzwerkverbindungen, Datenbankverbindungs-URLs, Benutzernamen / Passwörtern usw. dargestellt. Wenn sie veränderbar wären, könnten diese Parameter leicht geändert werden.String
Wird als Argument für das Laden von Klassen verwendet. Wenn veränderlich, kann dies dazu führen, dass eine falsche Klasse geladen wird (da veränderbare Objekte ihren Status ändern).Abgesehen davon
String
bedeutet Unveränderlichkeit von nur, dass Sie es nicht mit seiner öffentlichen API ändern können. Sie können die normale API mithilfe von Reflection umgehen. Siehe die Antwort hier .Wenn in Ihrem Beispiel
String
veränderlich war, betrachten Sie das folgende Beispiel:quelle
String
veränderlich ist, nimmt der Klassenlader die übergebene Zeichenfolge, erstellt eine Kopie und ändert ihre Kopie nicht. Wenn Sie an ein Problem mit veränderlichenjava.lang.String
s denken, denken Sie daran, wie C ++ dieses Problem löst (da es veränderbarestd::string
s hat.Java-Entwickler entscheiden, dass Strings aufgrund des folgenden Aspekts Design, Effizienz und Sicherheit unveränderlich sind .
Design Strings werden in einem speziellen Speicherbereich im Java-Heap erstellt, der als "String Intern Pool" bezeichnet wird. Während Sie einen neuen String erstellen (nicht bei Verwendung des String () - Konstruktors oder anderer String-Funktionen, die intern den String () - Konstruktor zum Erstellen eines neuen String-Objekts verwenden; der String () - Konstruktor erstellt immer eine neue String-Konstante im Pool, es sei denn, wir Rufen Sie die Methode intern () auf Variable ) auf, die den Pool durchsucht, um zu überprüfen, ob sie bereits vorhanden ist. Wenn es vorhanden ist, geben Sie die Referenz des vorhandenen String-Objekts zurück. Wenn der String nicht unveränderlich ist, führt das Ändern des Strings mit einer Referenz zu einem falschen Wert für die anderen Referenzen.
Nach diesem Artikel auf DZone:
quelle
Wir können nicht sicher sein, was Java-Designer beim Entwerfen tatsächlich gedacht haben,
String
aber wir können diese Gründe nur aus den Vorteilen schließen, die wir aus der Unveränderlichkeit von Strings ziehen, von denen einige sind1. Existenz eines String Constant Pools
Wie unter Warum String im String Constant Pool gespeichert wird beschrieben Artikel Zeichenfolgen im Artikel " , erstellt jede Anwendung zu viele Zeichenfolgenobjekte, um zu verhindern, dass JVM zuerst viele Zeichenfolgenobjekte erstellt und diese dann im Müll sammelt. JVM speichert alle String-Objekte in einem separaten Speicherbereich namens String-Konstantenpool und verwendet Objekte aus diesem zwischengespeicherten Pool erneut.
Immer wenn wir ein String-Literal erstellen, prüft JVM zuerst, ob dieses Literal bereits im konstanten Pool vorhanden ist oder nicht, und wenn es dort vorhanden ist, zeigt eine neue Referenz auf dasselbe Objekt in SCP.
In obigem Beispiel String - Objekt mit Wert
Naresh
wird nur einmal im SCP erstellt erhalten und alle Referenza
,b
,c
wird auf das gleiche Objekt zeigen , aber was ist, wenn wir in machen ändern versuchena
zBa.replace("a", "")
.Idealerweise
a
sollte WertNresh
aberb
,c
sollte da als Endverbraucher unverändert bleiben wir die Veränderung in machena
nur. Und wir wissena
,b
,c
alle weisen das gleiche Objekt so , wenn wir eine Änderung vornehmena
, andere auch die Änderung widerspiegeln.Die Unveränderlichkeit von Zeichenfolgen bewahrt uns jedoch vor diesem Szenario und wird sich aufgrund der Unveränderlichkeit des Zeichenfolgenobjekts
Naresh
niemals ändern. Wenn wir also Änderungena
anstelle von Änderungen am Zeichenfolgenobjekt vornehmen,Naresh
erstellt JVM ein neues Objekt, weist es zua
und nimmt dann Änderungen an diesem Objekt vor.Ein String-Pool ist also nur aufgrund der Unveränderlichkeit von String möglich. Wenn String nicht unveränderlich gewesen wäre, hätte das Zwischenspeichern und Wiederverwenden von String-Objekten keine Möglichkeit, da Variablen den Wert geändert und andere beschädigt hätten.
Und deshalb wird es von JVM ganz speziell gehandhabt und hat einen speziellen Speicherbereich erhalten.
2. Gewindesicherheit
Ein Objekt wird als threadsicher bezeichnet, wenn mehrere Threads darauf ausgeführt werden, aber keiner von ihnen kann seinen Status beschädigen, und das Objekt hat zu jedem Zeitpunkt für jeden Thread denselben Status.
Da wir ein unveränderliches Objekt nach seiner Erstellung von niemandem ändern können, ist jedes unveränderliche Objekt standardmäßig threadsicher. Wir müssen keine Thread-Sicherheitsmaßnahmen anwenden, wie z. B. das Erstellen synchronisierter Methoden.
Aufgrund seiner unveränderlichen Natur kann das String-Objekt von mehreren Threads gemeinsam genutzt werden, und selbst wenn es von vielen Threads manipuliert wird, ändert es seinen Wert nicht.
3. Sicherheit
In jeder Anwendung müssen wir mehrere Geheimnisse übergeben, z. B. Benutzername \ Kennwörter des Benutzers, Verbindungs-URLs, und im Allgemeinen werden alle diese Informationen als Zeichenfolgenobjekt übergeben.
Angenommen, String wäre nicht unveränderlich gewesen, würde dies eine ernsthafte Sicherheitsbedrohung für die Anwendung darstellen, da diese Werte geändert werden dürfen. Wenn dies zulässig ist, werden diese möglicherweise aufgrund von falsch geschriebenem Code oder einer anderen Person geändert haben Zugriff auf unsere variablen Referenzen.
4. Laden der Klasse
Wie unter Erstellen von Objekten durch Reflektion in Java mit Beispiel erläutert , können wir verwenden
Class.forName("class_name")
Methode eine Klasse in den Speicher laden, die wiederum andere Methoden dazu aufruft. Und selbst JVM verwendet diese Methoden, um Klassen zu laden.Wenn Sie jedoch klar sehen, dass alle diese Methoden den Klassennamen als Zeichenfolgenobjekt akzeptieren, werden beim Laden von Java-Klassen Zeichenfolgen verwendet, und die Unveränderlichkeit bietet Sicherheit, von der die richtige Klasse geladen wird
ClassLoader
.Angenommen, String wäre nicht unveränderlich gewesen und wir versuchen zu laden,
java.lang.Object
welcheorg.theft.OurObject
dazwischen geändert werden, und jetzt haben alle unsere Objekte ein Verhalten, das jemand für unerwünschte Dinge verwenden kann.5. HashCode-Caching
Wenn wir Hashing-bezogene Operationen an einem Objekt ausführen
hashCode()
möchten, müssen wir die Methode überschreiben und versuchen, unter Verwendung des Status des Objekts einen genauen Hashcode zu generieren. Wenn sich der Status eines Objekts ändert, sollte sich auch sein Hashcode ändern.Da String unveränderlich ist, wird der Wert, den ein String-Objekt enthält, niemals geändert, was bedeutet, dass sich auch sein Hashcode nicht ändert, was der String-Klasse die Möglichkeit gibt, ihren Hashcode während der Objekterstellung zwischenzuspeichern.
Ja, das String-Objekt speichert seinen Hashcode zum Zeitpunkt der Objekterstellung im Cache, was es zum idealen Kandidaten für Hashing-bezogene Operationen macht, da der Hashcode nicht erneut berechnet werden muss, was uns Zeit spart. Aus diesem Grund wird String hauptsächlich als
HashMap
Schlüssel verwendet.Lesen Sie mehr darüber, warum String in Java unveränderlich und endgültig ist .
quelle
Wichtigster Grund laut diesem Artikel auf DZone:
Hoffe es wird dir helfen.
quelle
Ich habe diesen Beitrag gelesen, warum String in Java unveränderlich oder endgültig ist, und nehme an, dass Folgendes der wichtigste Grund sein kann:
quelle
Du hast recht.
String
in Java verwendet das Konzept desString Pool
Literal. Wenn eine Zeichenfolge erstellt wird und die Zeichenfolge bereits im Pool vorhanden ist, wird die Referenz der vorhandenen Zeichenfolge zurückgegeben, anstatt ein neues Objekt zu erstellen und seine Referenz zurückzugeben. Wenn eine Zeichenfolge nicht unveränderlich ist, wird die Zeichenfolge mit einer Referenz geändert führen zu dem falschen Wert für die anderen Referenzen.Ich würde noch etwas hinzufügen, da
String
es unveränderlich ist, für Multithreading sicher ist und eine einzelne String-Instanz von verschiedenen Threads gemeinsam genutzt werden kann. Dadurch wird die Verwendung der Synchronisation für die Thread-Sicherheit vermiedenthread safe
. Strings sind implizit .quelle
String-Klasse
FINAL
bedeutet, dass Sie keine Klasse erstellen können, um sie zu erben, die Grundstruktur zu ändern und den Sting veränderbar zu machen.Eine andere Instanzvariable und Methoden der String-Klasse, die bereitgestellt werden, sind so, dass Sie das
String
einmal erstellte Objekt nicht mehr ändern können .Der Grund, den Sie hinzugefügt haben, macht den String überhaupt nicht unveränderlich. Dies alles sagt aus, wie der String im Heap gespeichert ist. Auch der String-Pool macht den großen Unterschied in der Leistung
quelle
String wird von Sun-Mikrosystemen als unveränderlich angegeben, da String als Schlüssel für die Kartensammlung gespeichert werden kann. StringBuffer ist veränderbar. Aus diesem Grund kann es nicht als Schlüssel im Kartenobjekt verwendet werden
quelle
Der wichtigste Grund dafür, dass ein String in Java unveränderlich gemacht wird, ist die Sicherheitsüberlegung . Als nächstes wäre Caching .
Ich glaube, andere Gründe, wie Effizienz, Parallelität, Design und String-Pool, ergeben sich aus der Tatsache, dass String unveränderlich gemacht wurde. Zum Beispiel. Der String-Pool konnte erstellt werden, da der String unveränderlich war und nicht umgekehrt.
Überprüfen Sie das Transkript des Gosling-Interviews hier
quelle
Zusätzlich zu den großartigen Antworten wollte ich einige Punkte hinzufügen. Wie Strings, Array enthält einen Verweis auf den Start des Arrays so , wenn Sie zwei Arrays
arr1
undarr2
und hat so etwas wiearr2 = arr1
dies die Referenz machenarr2
gleiche wiearr1
damit Wert zu verändern in einem von ihnen in Veränderung des anderen zum Beispiel führtEs würde nicht nur Fehler im Code verursachen, sondern kann (und wird) auch von böswilligen Benutzern ausgenutzt werden. Angenommen, Sie haben ein System, das das Administratorkennwort ändert. Der Benutzer muss zuerst das eingeben
newPassword
und dann das,oldPassword
wenn dasoldPassword
mitadminPass
dem Programm identisch ist , das Kennwort um ändernadminPass = newPassword
. Angenommen, das neue Kennwort hat dieselbe Referenz wie das Administratorkennwort, sodass ein fehlerhafter Programmierer möglicherweise einetemp
Variable erstellt, die das Administratorkennwort enthält, bevor der Benutzer Daten eingibt, wenn dasoldPassword
gleichetemp
Kennwort das Kennwort andernfalls ändertadminPass = temp
. Jemand, der weiß, dass er leicht das neue Passwort eingeben kann und niemals das alte Passwort und Abrakadabra eingibt, hat Administratorzugriff. Eine andere Sache, die ich beim Erlernen von Strings nicht verstanden habe, warum erstellt JVM nicht für jedes Objekt einen neuen String und hat einen eindeutigen Speicherplatz dafür, und Sie können dies einfach mit tun.new String("str");
Der Grund, den Sie nicht immer verwenden möchten,new
ist weil es nicht speichereffizient ist und in den meisten Fällen langsamer ist, lesen Sie mehr .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 char char ist, können Sie HELLO in HILLO ändern. Z.B,
Antworten:
Programmiersprachen haben unveränderliche Datenvariablen, so dass sie als Schlüssel im Schlüssel-Wert-Paar verwendet werden können. String-Variablen werden als Schlüssel / Indizes verwendet und sind daher unveränderlich .
quelle
Aus der
Security
Sicht können wir dieses praktische Beispiel verwenden:quelle