web-dev-qa-db-de.com

Warum ist String in Java unveränderlich?

Ich wurde in einem Interview gefragt, warum String unveränderlich ist

Ich habe so geantwortet:

Wenn wir eine Zeichenfolge in Java erstellen, wie String s1="hello";, dann eine Das Objekt wird im string-Pool (Hallo) erstellt und s1 wird .__ sein. zeigt auf hello. Wenn wir wieder String s2="hello"; machen, dann Ein anderes Objekt wird nicht erstellt, aber s2 verweist auf hello weil JVM zuerst überprüft, ob das gleiche Objekt in .__ vorhanden ist. string pool oder nicht.Wenn nicht vorhanden, wird nur ein neuer erstellt, andernfalls nicht.

Wenn nun angenommen wird, dass Java die Zeichenfolge ändern kann, ändern wir s1 in hello world. Dann wird der s2 - Wert ebenfalls hello world sein, sodass Java String unveränderlich ist.

Kann mir jemand sagen, ob meine Antwort richtig oder falsch ist?

152
rocking

String ist aus mehreren Gründen unveränderlich, hier eine Zusammenfassung:

  • Security: Die Parameter werden normalerweise als String in Netzwerkverbindungen, Datenbankverbindungs-URLs, Benutzernamen/Kennwörtern usw. dargestellt. Wenn es veränderbar wäre, könnten diese Parameter leicht geändert werden.
  • Synchronization und Parallelität: Durch die automatische Änderung der Zeichenfolge werden sie für den Thread sicher. Dadurch werden Synchronisierungsprobleme gelöst.
  • Caching: Wenn der Compiler Ihre String-Objekte optimiert, erkennt er, dass zwei Objekte denselben Wert haben (a = "test" und b = "test") und Sie daher nur ein String-Objekt benötigen (für a und b Diese beiden zeigen auf dasselbe Objekt.
  • Class loading: String wird als Argument für das Laden von Klassen verwendet. Bei einer veränderlichen Komponente kann dies dazu führen, dass eine falsche Klasse geladen wird (weil veränderliche Objekte ihren Status ändern).

Die Unveränderlichkeit von String bedeutet jedoch nur, dass Sie sie nicht mit ihrer ö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änderbar war, betrachten Sie das folgende Beispiel:

  String a="stack";
  System.out.println(a);//prints stack
  a.setValue("overflow");
  System.out.println(a);//if mutable it would print overflow
140
user508434

Java-Entwickler entscheiden, dass Strings aufgrund der folgenden Aspekte Design, Effizienz und Sicherheit unveränderlich sind.

Design Zeichenfolgen werden in einem speziellen Speicherbereich in Java-Heap erstellt, der als "String Intern-Pool" bezeichnet wird. Während Sie einen neuen String erstellen (Nicht bei Verwendung des String () - Konstruktors oder einer anderen String-Funktion, die intern den String () - Konstruktor zum Erstellen eines neuen String-Objekts verwendet; der String () - Konstruktor erstellt immer eine neue String-Konstante im Pool, sofern wir dies nicht tun Rufen Sie die Methode intern () ) auf. Es durchsucht den Pool, um zu prüfen, ob es bereits vorhanden ist . Falls vorhanden, geben Sie den Verweis auf das vorhandene String-Objekt zurück. . Wenn der String nicht unveränderlich ist Wenn Sie den String mit einer Referenz ändern, führt dies zu einem falschen Wert für die anderen Referenzen.

Laut diesem Artikel über DZone:

Sicherheit String wird häufig als Parameter für viele Java-Klassen verwendet, z. Netzwerkverbindung, Öffnen von Dateien usw. Wäre String nicht unveränderlich, würde eine Verbindung oder Datei geändert und dies würde zu einem ernsthaften Sicherheitsrisiko führen. Veränderliche Zeichenfolgen können auch in Reflection ein Sicherheitsproblem verursachen, da die Parameter Zeichenfolgen sind.

Effizienz Der Hashcode von String wird häufig in Java verwendet. Zum Beispiel in einer HashMap. Unveränderlich zu sein garantiert, dass der Hashcode immer derselbe ist, sodass er ohne Beeinträchtigung der Änderungen zwischengespeichert werden kann. Das bedeutet, dass der Hashcode nicht bei jeder Verwendung neu berechnet werden muss.

40
Alex Mathew

Wichtigster Grund laut this Artikel über DZone:

String Konstantenpool ... Wenn string veränderbar ist, führt das Ändern der Zeichenfolge mit einer Referenz zu einem falschen Wert für die anderen Referenzen.

Sicherheit

String wird häufig als Parameter für viele Java-Klassen verwendet, z. Netzwerkverbindung, Öffnen von Dateien usw. Wäre String nicht unveränderlich, würde eine Verbindung oder Datei geändert und dies würde zu einem ernsthaften Sicherheitsrisiko führen. ...

Ich hoffe es wird dir helfen.

20

Wir können uns nicht sicher sein, was Java Designer beim Entwerfen tatsächlich gedacht haben String], aber wir können diese Gründe nur auf der Grundlage der Vorteile ableiten, die wir aus der Unveränderlichkeit von Strings ziehen, von denen einige sind

1. Existenz von String Constant Pool

Wie in Warum String in String Constant Pool gespeichert wird beschrieben, erstellt jede Anwendung zu viele String-Objekte, um JVM davor zu bewahren, zuerst viele String-Objekte zu erstellen und diese dann durch Garbage Collection zu sammeln. JVM speichert alle Zeichenfolgenobjekte in einem separaten Speicherbereich namens String constant pool und verwendet Objekte aus diesem zwischengespeicherten Pool erneut.

Immer wenn wir ein Zeichenfolgenliteral erstellen, überprüft JVM zuerst, ob dieses Literal bereits in einem konstanten Pool vorhanden ist oder nicht, und wenn es vorhanden ist, zeigt eine neue Referenz auf dasselbe Objekt in SCP.

String a = "Naresh";
String b = "Naresh";
String c = "Naresh";

Im obigen Beispiel wird ein String-Objekt mit dem Wert Naresh nur einmal in SCP erstellt, und alle Verweise a, b, c verweisen jedoch auf dasselbe Objekt was ist, wenn wir versuchen, Änderungen in a vorzunehmen, z a.replace("a", "").

Idealerweise sollte a den Wert Nresh haben, aber b, c sollte unverändert bleiben, da wir als Endbenutzer die Änderung in a nur. Und wir wissen, dass a, b, c alle auf dasselbe Objekt zeigen. Wenn wir also eine Änderung in a vornehmen, sollten andere die Änderung ebenfalls widerspiegeln.

Die Unveränderlichkeit von Strings erspart uns dieses Szenario und aufgrund der Unveränderlichkeit des String-Objekts wird sich das String-Objekt Naresh niemals ändern. Wenn wir also eine Änderung an a anstelle einer Änderung am Zeichenfolgenobjekt Naresh vornehmen, erstellt JVM ein neues Objekt, weist es a zu 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 von String-Objekten und deren Wiederverwendung 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.

2. Fadensicherheit

Ein Objekt wird als threadsicher bezeichnet, wenn mehrere Threads darauf ausgeführt werden, aber keiner von ihnen in der Lage ist, seinen Status zu beschädigen, und wenn ein Objekt zu einem beliebigen Zeitpunkt für jeden Thread den gleichen Status aufweist.

Da ein unveränderliches Objekt nach seiner Erstellung von niemandem geändert werden kann, ist jedes unveränderliche Objekt standardmäßig threadsicher. Es müssen keine Thread-Sicherheitsmaßnahmen angewendet werden, z. B. das Erstellen synchronisierter Methoden.

Aufgrund seiner unveränderlichen Natur kann ein String-Objekt von mehreren Threads gemeinsam genutzt werden, und selbst wenn es von vielen Threads bearbeitet wird, ändert es seinen Wert nicht.

3. Sicherheit

In jeder Anwendung müssen wir mehrere Geheimnisse weitergeben, z. Benutzername des Benutzers\Kennwörter, Verbindungs-URLs und im Allgemeinen alle diese Informationen werden als String-Objekt übergeben.

Angenommen, String wäre in seiner Natur nicht unveränderlich, 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 Werte möglicherweise aufgrund von falsch geschriebenem Code oder einer anderen Person geändert haben Zugriff auf unsere variablen Referenzen.

4. Laden der Klasse

Wie in Erstellen von Objekten durch Reflection in Java mit Example erläutert, können wir mit der Class.forName("class_name") -Methode eine Klasse in den Speicher laden, die wiederum andere Methoden aufruft Auch JVM verwendet diese Methoden, um Klassen zu laden.

Wenn Sie jedoch deutlich sehen, dass alle diese Methoden den Klassennamen als Zeichenfolgeobjekt akzeptieren, werden Zeichenfolgen in Java Laden von Klassen und Unveränderlichkeit bietet Sicherheit, dass die richtige Klasse von ClassLoader.

Angenommen, String wäre nicht unveränderlich und wir versuchen, Java.lang.Object Zu laden, das dazwischen in org.theft.OurObject Geändert wird, 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 für ein Objekt ausführen möchten, müssen wir die hashCode() -Methode überschreiben und versuchen, einen genauen Hashcode unter Verwendung des Status des Objekts zu generieren. Wenn sich der Status eines Objekts ändert, sollte sich auch der Hashcode ändern.

Da String unveränderlich ist, wird der Wert, den ein String-Objekt enthält, niemals geändert, was bedeutet, dass sich auch der Hashcode nicht ändert, wodurch die String-Klasse die Möglichkeit erhält, 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 Zeit spart. Aus diesem Grund wird String meist als HashMap - Schlüssel verwendet.

Lesen Sie mehr über Warum String in Java unveränderlich und endgültig ist .

20
Naresh Joshi

Ich habe diesen Beitrag gelesen Warum String in Java unveränderlich oder final ist und nehme an, dass Folgendes der wichtigste Grund sein kann:

String ist in Java unveränderlich, da String-Objekte in .__ zwischengespeichert sind. String-Pool. Da zwischengespeicherte String-Literale für mehrere .__ freigegeben sind. clients Es besteht immer ein Risiko, dass die Aktion eines Clients Auswirkungen auf .__ hat. alle anderen Kunden.

4
Tho

Du hast recht. String in Java verwendet das Konzept von String 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 führt zu einem falschen Wert für die anderen Referenzen.

Ich würde noch eine weitere Sache hinzufügen, da String unveränderlich ist, es für Multithreading sicher ist und eine einzelne String-Instanz von verschiedenen Threads gemeinsam genutzt werden kann. Dies vermeidet die Verwendung der Synchronisierung für die Thread-Sicherheit. Strings sind implizit thread safe.

1
Akshay Gupta

String ist unveränderlich, weil: -

1. Design: - String-Pool ist nur möglich, weil String in Java unveränderlich ist. Auf diese Weise spart Java Runtime viel Java-Heap-Speicherplatz, da verschiedene String-Variablen auf dieselbe String-Variable im Pool verweisen können. Wenn String nicht unveränderlich gewesen wäre, wäre das String-Interning nicht möglich gewesen, denn wenn eine Variable den Wert geändert hätte, wäre dieser Wert auch für andere Variablen übernommen worden.

2. Sicherheit: - Wenn String nicht unveränderlich ist, führt dies zu einer erheblichen Sicherheitsbedrohung für die Anwendung. Datenbankbenutzername und -kennwort werden beispielsweise als Zeichenfolge übergeben, um die Datenbankverbindung abzurufen, und in der Socketprogrammierung. Da String unveränderlich ist, kann der Wert nicht geändert werden. Andernfalls kann ein Hacker den angegebenen Wert ändern, um Sicherheitsprobleme in der Anwendung zu verursachen.

3. Thread Safe: - Da String unveränderlich ist, ist es für Multithreading sicher und eine einzelne String-Instanz kann von verschiedenen Threads gemeinsam genutzt werden. Dies vermeidet die Verwendung der Synchronisierung für die Thread-Sicherheit. Strings sind implizit threadsicher

4. classloader: - Strings werden im Java-Classloader verwendet. Die Unveränderlichkeit bietet Sicherheit, dass die richtige Klasse von Classloader geladen wird. Stellen Sie sich beispielsweise eine Instanz vor, in der Sie versuchen, die Java.sql.Connection-Klasse zu laden, aber der Wert, auf den verwiesen wird, in die myhacked.Connection-Klasse geändert wird, die unerwünschte Aktionen für Ihre Datenbank bewirken kann.

5. Caching: - Da String unveränderlich ist, wird der Hashcode zum Zeitpunkt der Erstellung zwischengespeichert und muss nicht erneut berechnet werden. Dies macht ihn zu einem großartigen Kandidaten für Schlüssel in einer Map. Die Verarbeitung ist schneller als bei anderen HashMap-Schlüsselobjekten. Aus diesem Grund wird String meistens als Object-Objekt als HashMap-Schlüssel verwendet .. __ Oben sind einige der Gründe, aus denen ich mir vorstellen könnte, dass dies die Vorteile der String-Unveränderlichkeit zeigt. Es ist eine großartige Funktion der Java-String-Klasse und macht sie besonders.

1
Neeraj Gahlawat

Neben den großartigen Antworten wollte ich noch ein paar Punkte hinzufügen. Wie Strings enthält auch Array einen Verweis auf den Anfang des Arrays. Wenn Sie also zwei Arrays arr1 und arr2 erstellen und etwas wie arr2 = arr1 tun, wird der Verweis auf arr2 gleich wie arr1. Wenn Sie also einen der Arrays ändern, ändert sich der Wert in einem der Arrays andere zum Beispiel

public class Main {
    public static void main(String[] args) {
        int[] a = {1, 2, 3, 4};
        int[] b = a;
        a[0] = 8;
        b[1] = 7;
        System.out.println("A: " + a[0] + ", B: " + b[0]);
        System.out.println("A: " + a[1] + ", B: " + b[1]);
        //outputs
        //A: 8, B: 8
        //A: 7, B: 7
    }
}

Nicht nur, dass es Fehler im Code verursachen würde, sondern auch von böswilligen Benutzern ausgenutzt werden kann (und wird). Angenommen, Sie haben ein System, das das Administratorkennwort ändert. Der Benutzer muss zuerst newPassword und dann oldPassword eingeben, wenn oldPassword mit adminPass identisch ist. Das Programm ändert das Kennwort mit adminPass = newPassword. Angenommen, das neue Kennwort hat dieselbe Referenz wie das Administratorkennwort, sodass ein fehlerhafter Programmierer eine Variable temp erstellen kann, in der das Administratorkennwort gespeichert wird, bevor der Benutzer Daten eingibt, wenn oldPassword gleich temp ist. Andernfalls adminPass = temp. Jemand, der weiß, dass das neue Passwort leicht eingegeben werden kann, und niemals das alte Passwort und das Abrakadabra, das er Administratorzugriff hat, eingeben. Eine andere Sache, die ich nicht verstanden habe, als ich über Strings erfuhr, warum erstellt die JVM nicht für jedes Objekt einen neuen String und hat einen eindeutigen Platz im Speicher, und Sie können dies einfach mit new String("str"); tun. Der Grund, aus dem Sie nicht immer Gebrauch machen wollen new ist, weil es nicht speichereffizient ist und in den meisten Fällen langsamer ist read more .

0
Ãly Hâñý

String wird von Sun-Mikrosystemen als unveränderlich angegeben, da String als Schlüssel in der Map-Sammlung gespeichert werden kann. StringBuffer ist veränderlich

Der wichtigste Grund dafür, dass ein String in Java unveränderlich gemacht wird, ist Security. Das nächste wäre Caching

Ich glaube, dass andere Gründe wie Effizienz, Parallelität, Design und string pool aus der Tatsache stammen, dass String in unveränderlich gemacht wurde. Für zB String Pool konnte erstellt werden, da String nicht veränderbar war und nicht umgekehrt.

Überprüfen Sie das Transkript des Gosling-Interviews hier

Aus strategischer Sicht tendieren sie dazu, öfter störungsfrei zu sein. Es gibt normalerweise Dinge, die Sie mit unveränderlichen Objekten tun können, die Sie mit veränderlichen Dingen nicht machen können, z. B. das Ergebnis zwischenspeichern. Wenn Sie einer Methode zum Öffnen von Dateien eine Zeichenfolge übergeben oder wenn Sie eine Zeichenfolge in einer Benutzeroberfläche an einen Konstruktor für ein Label übergeben, übergeben Sie in einigen APIs (wie in vielen Windows-APIs) ein Array von Zeichen. Der Empfänger dieses Objekts muss es wirklich kopieren, da er nichts über die Speicherlebensdauer des Objekts weiß. Und sie wissen nicht, was mit dem Objekt passiert, ob es unter ihren Füßen verändert wird.

Sie werden fast gezwungen, das Objekt zu replizieren, weil Sie nicht wissen, ob Sie es besitzen oder nicht. Und das Schöne an unveränderlichen Objekten ist, dass die Antwort lautet: "Ja, natürlich tun Sie das." Denn die Frage des Eigentums, wer das Recht hat, es zu ändern, existiert nicht.

Eines der Dinge, die Strings dazu zwangen, unveränderlich zu sein, war die Sicherheit. Sie haben eine Methode zum Öffnen von Dateien. Sie übergeben einen String daran. Und dann werden alle Arten von Authentifizierungsprüfungen durchgeführt, bevor der Betriebssystemaufruf ausgeführt wird. Wenn Sie es schaffen, etwas zu tun, das den String nach der Sicherheitsprüfung und vor dem Aufruf des Betriebssystems effektiv verändert hat, dann sind Sie dran. Aber Strings sind unveränderlich, sodass diese Art von Angriff nicht funktioniert. Dieses genaue Beispiel hat das wirklich gefordert Strings sind unveränderlich

0
Sameer Sinha

Wenn HELLO Ihr String ist, können Sie HELLO nicht in HILLO ändern. Diese Eigenschaft wird als unveränderliche Eigenschaft bezeichnet. 

Sie können eine String-Variable mit mehreren Zeigern haben, um auf HELLO String zu zeigen. 

Wenn HELLO char Array ist, können Sie HELLO in HILLO ändern. Z.B, 

char[] charArr = 'HELLO';
char[1] = 'I'; //you can do this

Antworten:  

Programmiersprachen verfügen über unveränderliche Datenvariablen, so dass sie als Schlüssel in einem Schlüsselpaar verwendet werden können. String-Variablen werden als Schlüssel/Indizes verwendet, daher sind sie unveränderlich

0
Uddhav Gautam

Die String-Klasse ist FINAL. Dies bedeutet, dass Sie keine Klasse erstellen können, um sie zu erben und 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-Objekt nicht mehr ändern können, sobald es erstellt wurde.

Der Grund, den Sie hinzugefügt haben, macht den String überhaupt nicht unveränderlich. All dies sagt aus, wie der String in heap gespeichert wird. Auch ein String-Pool macht den großen Unterschied in der Leistung aus

0
Kick