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 sind
1. 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.
String a = "Naresh";
String b = "Naresh";
String c = "Naresh";
In obigem Beispiel String - Objekt mit Wert Naresh
wird nur einmal im SCP erstellt erhalten und alle Referenz a
, b
, c
wird auf das gleiche Objekt zeigen , aber was ist, wenn wir in machen ändern versuchen a
zB a.replace("a", "")
.
Idealerweise a
sollte Wert Nresh
aber b
, c
sollte da als Endverbraucher unverändert bleiben wir die Veränderung in machen a
nur. Und wir wissen a
, b
, c
alle weisen das gleiche Objekt so , wenn wir eine Änderung vornehmen a
, 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 Änderungen a
anstelle von Änderungen am Zeichenfolgenobjekt vornehmen, Naresh
erstellt JVM ein neues Objekt, weist es zu a
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 verwendenClass.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
welche org.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 .