Heim  >  Artikel  >  Backend-Entwicklung  >  String StringBuffer StringBuilder wird verwendet

String StringBuffer StringBuilder wird verwendet

巴扎黑
巴扎黑Original
2016-12-20 15:49:411306Durchsuche

String-String-Konstante
StringBuffer-String-Variable (Thread-sicher)
StringBuilder-String-Variable (nicht Thread-sicher)
Kurz gesagt besteht der Hauptleistungsunterschied zwischen String-Typ und StringBuffer-Typ darin, dass String ist Da es sich um ein unveränderliches Objekt handelt, entspricht jede Änderung des String-Typs tatsächlich dem Generieren eines neuen String-Objekts und dem anschließenden Zeigen des Zeigers auf das neue String-Objekt. Daher ist es am besten, String nicht für Strings zu verwenden, deren Inhalt sich häufig ändert Denn jedes Mal, wenn ein Objekt generiert wird, wirkt sich dies auf die Systemleistung aus. Insbesondere wenn sich zu viele nicht referenzierte Objekte im Speicher befinden, beginnt der GC zu arbeiten und die Geschwindigkeit wird definitiv ziemlich langsam sein.
Wenn Sie die StringBuffer-Klasse verwenden, ist das Ergebnis unterschiedlich. Jedes Ergebnis wird auf das StringBuffer-Objekt selbst angewendet, anstatt ein neues Objekt zu generieren und dann die Objektreferenz zu ändern. Daher empfehlen wir im Allgemeinen die Verwendung von StringBuffer, insbesondere wenn sich String-Objekte häufig ändern. In einigen Sonderfällen wird die String-Verkettung von String-Objekten von der JVM tatsächlich als die Verkettung von StringBuffer-Objekten interpretiert, sodass in diesen Fällen die Geschwindigkeit von String-Objekten nicht langsamer ist als die von StringBuffer-Objekten, insbesondere die folgenden String-Objekte Unter diesen ist die String-Effizienz viel schneller als bei StringBuffer:
String S1 = „This is only a“ + „simple“ + „test“; append("simple").append("test");
Sie werden überrascht sein, dass die Geschwindigkeit beim Generieren von String S1-Objekten einfach zu hoch ist und StringBuffer derzeit überhaupt keinen Geschwindigkeitsvorteil hat. Tatsächlich ist dies ein Trick der JVM. In den Augen der JVM ist dieser
String S1 = „This is only a“ + „simple“ + „test“ tatsächlich:
String S1 = „ Dies ist nur ein einfacher Test“, daher dauert es natürlich nicht lange. Aber was hier jeder beachten sollte, ist, dass die Geschwindigkeit nicht so hoch sein wird, wenn er von einem anderen String-Objekt stammt, zum Beispiel:
String S2 = „Das ist nur ein“
String S3 = „einfach“; ;
String S4 = „test“;
String S1 = S2 +S3 + S4;
Zu diesem Zeitpunkt verhält sich die JVM im Allgemeinen in einigen Fällen StringBuffer > String
StringBuffer
Java.lang.StringBuffer threadsichere veränderbare Zeichenfolge. Ein String-Puffer ähnlich wie String, der jedoch nicht geändert werden kann. Obwohl es zu jedem Zeitpunkt eine bestimmte Zeichenfolge enthält, können Länge und Inhalt dieser Zeichenfolge durch bestimmte Methodenaufrufe geändert werden.
String-Puffer können sicher mit mehreren Threads verwendet werden. Diese Methoden können bei Bedarf synchronisiert werden, sodass alle Vorgänge auf einer bestimmten Instanz scheinbar in einer seriellen Reihenfolge ausgeführt werden, die mit der Reihenfolge der Methodenaufrufe jedes beteiligten Threads übereinstimmt.
Die Hauptoperationen auf StringBuffer sind die Append- und Insert-Methoden, die überladen werden können, um jede Art von Daten zu akzeptieren. Jede Methode wandelt die angegebenen Daten effektiv in eine Zeichenfolge um und hängt dann die Zeichen dieser Zeichenfolge an einen Zeichenfolgenpuffer an oder fügt sie ein. Die Append-Methode fügt diese Zeichen immer am Ende des Puffers hinzu; die Insert-Methode fügt Zeichen an einer angegebenen Stelle hinzu.
Wenn sich z beispielsweise auf ein Zeichenfolgenpufferobjekt bezieht, dessen aktueller Inhalt „start“ ist, führt dieser Methodenaufruf z.append(„le“) dazu, dass der Zeichenfolgenpuffer „startle“ enthält und z.insert( 4, „le“) ändert den String-Puffer so, dass er „starlet“ enthält.
In den meisten Fällen StringBuilder > StringBuffer
java.lang.StringBuilde
java.lang.StringBuilder Eine variable Zeichenfolge ist neu in 5.0. Diese Klasse stellt eine StringBuffer-kompatible API bereit, garantiert jedoch keine Synchronisierung. Diese Klasse ist als Ersatz für StringBuffer konzipiert, wenn der String-Puffer von einem einzelnen Thread verwendet wird (was häufig vorkommt). Es wird empfohlen, nach Möglichkeit diese Klasse zu bevorzugen, da sie in den meisten Implementierungen schneller als StringBuffer ist. Die Methoden sind für beide grundsätzlich gleich.
============================================= === ======================
Detaillierte Erklärung der String-Klasse
1 .
2. Das Wesentliche der String-Klasse ist das Zeichenarray char[], und sein Wert kann nicht geändert werden. PRivate final char value[];
Öffnen Sie dann das API-Dokument der String-Klasse. Sie finden Folgendes:
3. Es gibt eine spezielle Möglichkeit, String-Klassenobjekte zu erstellen, nämlich die direkte Angabe von String x = „abc“, „abc“ bedeutet ein String-Objekt. Und x ist die Adresse des „abc“-Objekts, auch

als Referenz auf das „abc“-Objekt genannt.
4. String-Objekte können durch „+“ verkettet werden. Nach der Verkettung wird eine neue Zeichenfolge generiert. Sie können die Verkettung auch über concat() durchführen, was später beschrieben wird.
6. Java verwaltet beim Ausführen einen String-Pool. Die JavaDoc-Übersetzung ist als „String-Puffer“ sehr vage. Der String-Pool wird zum Speichern verschiedener zur Laufzeit generierter Strings verwendet,

Und der Inhalt der Zeichenfolgen im Pool wird nicht wiederholt. Dieser Pufferpool existiert nicht für allgemeine Objekte und die erstellten Objekte existieren nur im Stapelbereich der Methode.


5. Es gibt viele Möglichkeiten, Zeichenfolgen zu erstellen, die in drei Kategorien zusammengefasst werden können:
Verwenden Sie zunächst das Schlüsselwort new, um eine Zeichenfolge zu erstellen, z. B. String s1 = new String(" abc");
Zweitens direkt angeben. Beispiel: String s2 = "abc";
Drittens verwenden Sie die Verkettung, um eine neue Zeichenfolge zu generieren. Zum Beispiel: String s3 = „ab“ + „c“;

2. Erstellung eines String-Objekts

Die Erstellung eines String-Objekts ist ebenfalls sehr spezifisch.
Prinzip 1: Wenn Sie eine beliebige Methode zum Erstellen eines String-Objekts verwenden, verwendet die Java-Laufzeitumgebung (die JVM ausführt) dieses X, um festzustellen, ob sich im String-Pool ein String-Objekt mit demselben Inhalt befindet,

Wenn es nicht vorhanden ist, erstellen Sie einen String s im Pool, andernfalls fügen Sie ihn nicht dem Pool hinzu.

Prinzip 2: Solange Sie in Java das Schlüsselwort new zum Erstellen eines Objekts verwenden, wird auf jeden Fall ein neues Objekt erstellt (im Heap- oder Stack-Bereich).

Prinzip 3: Verwenden Sie die direkte Angabe oder verwenden Sie die reine String-Verkettung, um ein String-Objekt zu erstellen. Dann werden nur die Strings im String-Pool überprüft und verwaltet. Wenn sich im Pool kein String befindet, erstellen Sie einen Pool, sonst

Verstanden! Das String-Objekt wird jedoch niemals im Stapelbereich erstellt.

Prinzip 4: Durch die Verwendung eines Ausdrucks, der Variablen enthält, zum Erstellen eines String-Objekts wird nicht nur der String-Pool überprüft und verwaltet, sondern auch ein String-Objekt im Stapelbereich erstellt.

Darüber hinaus ist die intern()-Methode von String eine lokale Methode, die als öffentlicher nativer String intern() definiert ist. Der Wert der intern()-Methode besteht darin, Entwicklern die Konzentration auf
String-Pool. Wenn die interne Methode aufgerufen wird und der Pool bereits eine Zeichenfolge enthält, die diesem String-Objekt entspricht (wie durch die Methode equal(Object) bestimmt), wird die Zeichenfolge im Pool

zurückgegeben. Andernfalls wird dieses String-Objekt dem Pool hinzugefügt und ein Verweis auf dieses String-Objekt zurückgegeben.

3. Unveränderliche Klassen
Unveränderliche Zeichenfolgen haben einen großen Vorteil: Der Compiler kann die Zeichenfolge so festlegen, dass sie gemeinsam genutzt wird.
Unveränderliche String-Klassen haben einen wichtigen Vorteil: Es handelt sich nicht um gemeinsame Referenzen.

Um die Effizienz zu verbessern, hat JAVA eine spezielle Verarbeitung für den String-Typ durchgeführt und einen String-Pool für den String-Typ bereitgestellt.
Es gibt zwei Möglichkeiten, eine String-Typ-Variable zu definieren:
string name= „tom“;
string name =new string( „tom“)
Bei Verwendung der ersten Methode wird der String-Pool verwendet.
Bei Verwendung der zweiten Methode ist dies eine übliche Methode zum Deklarieren von Objekten
Wenn Sie die erste Methode verwenden und einen String deklarieren, dessen Inhalt ebenfalls „tom“ ist, wird der ursprüngliche Speicher im String-Pool verwendet, ohne ihn neu zuzuweisen saname = „tom“, zeigt auf denselben Speicher

Außerdem bezüglich des Problems, dass der String-Typ unveränderlich ist:
Der String-Typ ist unveränderlich, das heißt, wenn Sie einen String ändern möchten Objekt, wie zum Beispiel name = „madding“
, dann ändert die virtuelle Maschine nicht das ursprüngliche Objekt, sondern generiert ein neues Zeichenfolgenobjekt und lässt dann darauf verweisen. Wenn das ursprüngliche Objekt „tom“ ist, gibt es kein Objekt um darauf zu verweisen, und der Garbage-Collection-Mechanismus der virtuellen Maschine wird es empfangen.
Es wird gesagt, dass dies die Effizienz verbessern kann! ! !
============================================= === =======================final StringBuffer a = new StringBuffer("111");
final StringBuffer b = new StringBuffer ("222 ");
a=b;//Dieser Satz besteht die Kompilierung nicht
final StringBuffer a = new StringBuffer("111");/ /Die Kompilierung besteht
Es ist ersichtlich, dass final nur für den „Wert“ der Referenz gültig ist (d. h. die Speicheradresse). Dadurch wird die Referenz dazu gezwungen, nur auf das Objekt zu zeigen, auf das ursprünglich gezeigt wurde führt zu einem Fehler bei der Kompilierung. Für Änderungen an dem Objekt, auf das es verweist, ist final nicht verantwortlich.

Vier Beispiele für String-Konstanten-Pool-Probleme
Das Folgende ist eine vergleichende Analyse und ein Verständnis mehrerer häufiger Beispiele:

[1]
String a = "a1"
String b = "a" + 1;
System.out.println((a == b)); //result = true
String b = "a " + "true";
System.out.println((a == b)); //result = true
String a = "a3.4";
String b = "a" + 3.4;
System.out.println((a == b)); //result = true
Analyse: JVM optimiert die „+“-Verbindung von Zeichenfolgenkonstanten in den Wert nach der Verbindung während der Programmkompilierung. Nehmen Sie „a“ + 1 als Beispiel, nach der Compileroptimierung ist es bereits a1 in der Klasse. Der Wert seiner String-Konstante wird während der Kompilierung bestimmt, sodass das Endergebnis des obigen Programms wahr ist.

[2]
String a = "ab";
String bb = "b";
String b = "a" + bb; (a == b)); //result = false
Analyse: Bei String-Referenzen gibt es bei JVM einen String-Referenzwert in der „+“-Verbindung des Strings, und der Referenzwert ist während der Programmkompilierung nicht möglich Bestimmen Sie, dass „a“ + bb vom Compiler nicht optimiert werden kann. Es kann nur dynamisch zugewiesen werden, während das Programm ausgeführt wird, und die neue Adresse nach der Verbindung mit b zuweisen. Das Ergebnis des obigen Programms ist also falsch.

[3]
String a = "ab";
final String bb = "b";
String b = "a" + bb; ((a == b)); //result = true
Analyse: Der einzige Unterschied zu [3] besteht darin, dass die bb-Zeichenfolge bei endgültig geänderten Variablen zur Kompilierzeit A als Konstante analysiert wird Die lokale Kopie des Werts wird in einem eigenen Konstantenpool gespeichert oder in seinen Bytecode-Stream eingebettet.
Die Wirkung von „a“ + bb und „a“ + „b“ ist zu diesem Zeitpunkt also dieselbe. Daher ist das Ergebnis des obigen Programms wahr.

[4]
String a = "ab";
final String bb = getBB();
String b = "a" + bb; ((a == b)); //result = false
private static String getBB() { return "b" }
Analyse: JVM hat eine String-Referenz bb und ihr Wert kann beim Kompilieren nicht bestimmt werden Zeit: Erst nachdem die Methode während der Ausführung des Programms aufgerufen wurde, wird der Rückgabewert der Methode dynamisch mit „a“ verbunden und die Adresse b zugewiesen, sodass das Ergebnis des obigen Programms falsch ist.

Aus den obigen 4 Beispielen kann geschlossen werden:

String s = „a“ + „b“ + „c“; Es entspricht String s = „abc“; >
String a = "a";
String b = "b";
String s = a + b + c; , das Endergebnis ist gleich:

StringBuffer temp = new StringBuffer();
temp.append(a).append(b).append(c); toString ();
Aus den obigen Analyseergebnissen lässt sich leicht schließen, dass String den Verbindungsoperator (+) verwendet, um die Gründe für die Ineffizienz zu analysieren:

öffentlicher Klassentest {
public static void main(String args[]) {
String s = null;
for(int i = 0; i < 100; i++) { s += "a" }
}
}
Jedes Mal, wenn Sie + ausführen, wird ein StringBuilder-Objekt generiert und nach dem Anhängen weggeworfen. Wenn die Schleife das nächste Mal ankommt, wird ein StringBuilder-Objekt neu generiert und dann die Zeichenfolge angehängt, und diese Schleife wird bis zum Ende fortgesetzt. Wenn wir das StringBuilder-Objekt direkt zum Anhängen verwenden, können wir N-1 Mal das Erstellen und Zerstören von Objekten einsparen. Daher werden für Anwendungen, die eine Zeichenfolgenverkettung in einer Schleife erfordern, im Allgemeinen StringBuffer- oder StringBulider-Objekte für Anhängevorgänge verwendet.

Verständnis und Analyse der internen Methode des String-Objekts
public class Test4 {
private static String a = "ab";
public static void main(String[] args){
String s1 = "a";
String s2 = "b";
String s = s1 + s2;
System.out.println(s == a);//false
System . out.println(s.intern() == a);//true
}
}
Die Verwendung von Java ist hier ein ständiges Poolproblem. Bei der Operation s1+s2 wird tatsächlich ein neues Objekt im Heap erstellt. s speichert den Inhalt dieses neuen Objekts im Heap-Bereich, sodass die Werte von s und a nicht gleich sind. Wenn die Methode s.intern() aufgerufen wird, kann der Adresswert von s im Konstantenpool zurückgegeben werden. Da der Wert von a im Konstantenpool gespeichert ist, sind die Werte von s.intern und a gleich.

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn