JavaRush /Java-Blog /Random-DE /Übersetzung: String-Objekte in Java erstellen – mit „“ od...
FellowSparrow
Level 12
Lvov

Übersetzung: String-Objekte in Java erstellen – mit „“ oder Konstruktor?

Veröffentlicht in der Gruppe Random-DE
Original: Java-String mit „“ oder Konstruktor erstellen? Von X Wang Übersetzung: String-Objekte in Java erstellen – VerwendungIn Java kann eine Zeichenfolge mit zwei Methoden erstellt werden:
String x = "abc";
String y = new String("abc");
Was ist der Unterschied zwischen der Verwendung von doppelten Anführungszeichen und der Verwendung eines Konstruktors?

1. Doppelte Anführungszeichen vs. Konstrukteur

Diese Frage lässt sich anhand zweier einfacher Beispiele beantworten. Beispiel 1:
String a = "abcd";
String b = "abcd";
System.out.println(a == b);  // True
System.out.println(a.equals(b)); // True
a==bwahr, weil abeide bauf dasselbe Objekt verweisen – einen String, der als Literal (String-Literal unten) im Methodenbereich deklariert ist (wir verweisen den Leser auf die Quelle unserer Ressource: Top 8 Diagramme zum Verständnis von Java , Diagramm 8). Wenn dasselbe String-Literal mehr als einmal erstellt wird, wird nur eine Kopie des Strings im Speicher gespeichert, also nur eine Instanz davon (in unserem Fall „abcd“). Dies wird als „String-Internierung“ bezeichnet. Alle zur Kompilierzeit verarbeiteten String-Konstanten werden automatisch in Java interniert. Beispiel 2:
String c = new String("abcd");
String d = new String("abcd");
System.out.println(c == d);  // False
System.out.println(c.equals(d)); // True
c==dfalse, da csie dauf zwei verschiedene Objekte im Speicher (auf dem Heap) verweisen. Unterschiedliche Objekte haben immer unterschiedliche Referenzen. Dieses Diagramm veranschaulicht die beiden oben beschriebenen Situationen: Übersetzung: String-Objekte in Java erstellen – Verwendung

2. Internierung von Zeichenfolgen in der Programmausführungsphase

Der Autor bedankt sich bei LukasEder (der Kommentar unten stammt von ihm): String-Interning kann auch während der Programmausführung auftreten, selbst wenn zwei Strings mithilfe von Konstruktoren erstellt werden:
String c = new String("abcd").intern();
String d = new String("abcd").intern();
System.out.println(c == d);  // Now true
System.out.println(c.equals(d)); // True

3. Wann sind doppelte Anführungszeichen und wann Konstruktoren zu verwenden?

Da das Literal „abcd“ immer vom Typ String ist, wird bei Verwendung eines Konstruktors ein zusätzliches unnötiges Objekt erstellt. Daher sollten doppelte Anführungszeichen verwendet werden, wenn Sie nur eine Zeichenfolge erstellen müssen. Wenn Sie tatsächlich ein neues Objekt auf dem Heap erstellen müssen, sollten Sie einen Konstruktor verwenden. Anwendungsfälle werden hier gezeigt (Original) . (Ich stelle den übersetzten Text unten zur Verfügung. Ich empfehle Ihnen jedoch dennoch dringend, sich unter diesem Link mit dem Kommentatorencode vertraut zu machen.)

Die substring()-Methode in JDK 6 und JDK 7

Die Methode substring() in JDK 6 und JDK 7 von X Wang Die Methode substring(int beginIndex, int endIndex)in JDK 6 und JDK 7 ist unterschiedlich. Wenn Sie diese Unterschiede kennen, können Sie diese Methode besser nutzen. Der besseren Lesbarkeit halber substring()meinen wir im Folgenden die vollständige Syntax, d. h. substring(int beginIndex, int endIndex).

1. Was macht substring()?

Die Methode substring(int beginIndex, int endIndex)gibt eine Zeichenfolge zurück, die mit der Zeichennummer beginnt beginIndexund mit der Zeichennummer endet endIndex-1.
String x = "abcdef";
x = x.substring(1,3);
System.out.println(x);
Ausgabe:
bc

2. Was passiert, wenn substring() aufgerufen wird?

Möglicherweise wissen Sie, dass aufgrund der Unveränderlichkeit xbei der Zuweisung von x als Ergebnis von x.substring(1,3)auf xeine völlig neue Zeile verwiesen wird (siehe Diagramm): Übersetzung: String-Objekte in Java erstellen – VerwendungDieses Diagramm ist jedoch nicht vollständig korrekt. Es zeigt nicht, was tatsächlich im Heap vor sich geht. Was beim Aufruf tatsächlich passiert, substring()ist in JDK 6 und JDK 7 unterschiedlich.

3. substring() in JDK 6

Der String-Typ wird vom Array-Typ unterstützt char. In JDK 6 enthält die Klasse Stringdrei Felder: char value[], int offset, int count. Sie werden verwendet, um das tatsächliche Zeichenarray, den Index des ersten Zeichens im Array und die Anzahl der Zeichen in der Zeile zu speichern. Wenn die Methode aufgerufen wird substring(), erstellt sie eine neue Zeile, der Wert der Variablen zeigt jedoch immer noch auf dasselbe Array im Heap. Der Unterschied zwischen zwei Zeichenfolgen besteht in der Anzahl ihrer Zeichen und dem Indexwert des Startzeichens im Array. Übersetzung: String-Objekte in Java erstellen – VerwendungDer folgende Code ist vereinfacht und enthält nur die Grundlagen zur Veranschaulichung des Problems.
//JDK 6
String(int offset, int count, char value[]) {
	this.value = value;
	this.offset = offset;
	this.count = count;
}

public String substring(int beginIndex, int endIndex) {
	//check boundary
	return  new String(offset + beginIndex, endIndex - beginIndex, value);
}

4. Problem verursacht durch substring() in JDK 6

Wenn Sie eine SEHR lange Zeichenfolge haben, aber nur einen kleinen Teil davon benötigen, den Sie jedes Mal erhalten, wenn Sie verwenden substring(). Dies führt zu Ausführungsproblemen, da Sie nur einen kleinen Teil benötigen, aber trotzdem den gesamten String speichern müssen. Für JDK 6 ist die Lösung der folgende Code, der die Zeichenfolge in eine echte Teilzeichenfolge umwandelt:
x = x.substring(x, y) + ""
Benutzer STepeR hat eine Frage formuliert (siehe seinen Kommentar), und es schien notwendig, Punkt 4 hinzuzufügen. „Problem verursacht substring()durch JDK 6“ ist ein ausführlicheres Beispiel. Ich hoffe, dass dies die Antwort ist und anderen hilft, schnell herauszufinden, wo das Problem liegt. Hier ist der Code:
String a = "aLongLongString";
String b = a.substring(1, 2);
String c = a.substring(2, 6);
In JDK 7 verweisen Objekte vom Typ a, bdie durch den Aufruf einer Methode für ein Objekt vom Typ a erstellt wurden , auf zwei neu erstellte Arrays im Heap – for , for . Diese beiden neuen Arrays werden auf dem Heap ALONG mit dem ursprünglichen Array gespeichert, auf das durch a verwiesen wird. Diese. Das ursprüngliche Array verschwindet nirgendwo. Kehren wir nun zu JDK 6 zurück. In JDK 6 enthält ein Heap ein einzelnes Array . Nach der Ausführung der Codezeilen сStringsubstring()StringLbongLcaLongLongStringaLongLongString
String b = a.substring(1, 2);
String c = a.substring(2, 6);
Objekte bverweisen cauf dasselbe Array im Heap, das dem Objekt entspricht a: b- auf Elemente vom 1. Index bis zum 2., c- auf Elemente vom 2. Index bis zum 6. (Nummerierung beginnt bei 0, Erinnerung). Diese. Offensichtlich führt jeder weitere Zugriff auf Variablen boder c in JDK 6 tatsächlich dazu, dass die gewünschten Elemente des ursprünglichen Arrays in den Heap „gezählt“ werden. In JDK 7 führt jeder weitere Zugriff auf Variablen boder c zu einem Zugriff auf die erforderlichen kleineren Arrays, die bereits erstellt wurden und im Heap „leben“. Diese. Offensichtlich verbraucht JDK 7 in solchen Situationen physisch mehr Speicher. Aber stellen wir uns eine mögliche Option vor: Den Variablen werden bestimmte Teilzeichenfolgen der Variablen zugewiesen b, und in Zukunft verwendet jeder nur noch diese – Objekte und . Niemand greift mehr einfach auf die Variable a zu, es gibt keine Referenzen darauf (das meint der Autor des Artikels). Infolgedessen wird irgendwann der Garbage Collector ausgelöst, und (natürlich in der allgemeinsten Form) erhalten wir zwei verschiedene Situationen: JDK 6 : Das Objekt wird zerstört (Müll gesammelt) , ABER – das ursprüngliche riesige Array im Haufen ist lebendig; es wird ständig genutzt und . JDK 7: Objekt a wird zusammen mit dem ursprünglichen Array im Heap zerstört. Dies ist der Punkt in JDK 6, der zu einem Speicherverlust führen kann. cabcabc

5. substring() in JDK 7

Die Methode wurde in JDK 7 verbessert. In JDK 7 substring()wird tatsächlich ein neues Array auf dem Heap erstellt. Übersetzung: String-Objekte in Java erstellen – Verwendung
//JDK 7
public String(char value[], int offset, int count) {
	//check boundary
	this.value = Arrays.copyOfRange(value, offset, offset + count);
}

public String substring(int beginIndex, int endIndex) {
	//check boundary
	int subLen = endIndex - beginIndex;
	return new String(value, beginIndex, subLen);
}
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION