Frage

Wenn Sie zwei Instanzen eines String haben, und sie sind gleich, in Java werden sie den gleichen Speicher gemeinsam nutzen. Wie dies unter der Haube umgesetzt?

EDIT: Meine Anwendung verwendet eine große Anzahl von String-Objekten, von denen viele identisch sind. Was ist der beste Weg, die Verwendung von Java-String-Konstante Pool zu machen, wie das Erstellen von benutzerdefinierten Fliegengewicht Implementierung zu vermeiden?

War es hilfreich?

Lösung

Schauen Sie sich den Quellcode java.lang.String (Quelle für die gesamte Java-API ist Teil des JDK).

Um es zusammenzufassen: Ein String wickelt eine Subsequenz eines char[]. Das Träger char[] wird nie geändert. Dies wird erreicht, indem weder undicht noch diese char[] außerhalb der String Klasse zu erfassen. Es können jedoch mehrere Strings die gleiche char[] teilen (siehe Umsetzung von String.substring).

Es ist auch der Mechanismus der Internierung, wie in den anderen Antworten erklärt.

Andere Tipps

Wenn Sie zwei Instanzen eines String haben, und sie sind gleich, in Java werden sie den gleichen Speicher gemeinsam nutzen

Dies ist eigentlich nicht zu 100% wahr.

diese Blog-Post ist eine anständige Erklärung warum dies so ist, und was die Zeichenkette Pool ist.

Stringliterale ist in Java interniert, so ist es wirklich nur ein String-Objekt mit mehreren Referenzen (wenn sie gleich sind, was nicht immer der Fall ist). Siehe die java.net Artikel Alles über intern () für weitere Details.

Es gibt auch ein gutes Beispiel / Erläuterung in Abschnitt 3.10.5 Zeichenfolgenliteralen der JLS, dass die Gespräche über, wenn Strings werden interniert und wenn sie verschieden sein werden.

Das ist, gilt nicht notwendig. Beispiel:

String s1 = "hello";
String s2 = "hello";
System.out.println(s1 == s2); // true

aber:

String s1 = new String("hello");
String s2 = new String("hello");
System.out.println(s1 == s2); // false

Nun wird die zweite Form abgeraten. Einige (mich eingeschlossen) denken, dass String nicht einmal einen öffentlichen Konstruktor haben sollte. Eine bessere Version des obigen wäre:

String s1 = new String("hello").intern();
String s2 = new String("hello").intern();
System.out.println(s1 == s2); // true

Natürlich müssen Sie nicht diese für eine konstante String zu tun. Es ist illustrativ.

Der wichtige Punkt dabei ist, dass, wenn Sie eine String vergangen sind oder eines aus einer Funktion erhalten Sie nicht auf die String verlassen kann sein kanonische . A kanonische Object erfüllt diese Gleichheit:

a.equals(b) == b.equals(a) == (a == b)

für nicht-null Instanzen a, b, eines gegebenen Class.

Um Ihre editierten Frage zu beantworten, haben Sun JVMs eine -XX:+StringCache Option, die in meiner Beobachtung deutlich den Speicherbedarf eines String schweren Anwendung reduzieren kann.

Ansonsten haben Sie die Möglichkeit, Ihre Strings von Internierung, aber ich würde darüber vorsichtig sein. Strings, die sehr groß sind und nicht mehr noch verwies auf Speicher für das Leben des JVM verwenden.

Edit (als Antwort auf Kommentar): Ich fand first out über die StringCache Option von Tom Hawtin irgendeine Art von Caching von beschreibt einige Benchmarks zu verbessern. Meine Beobachtung, wenn ich es auf IDEA gesetzt war, dass der Speicherbedarf (nach einer vollständigen Garbage Collection) ging hinunter über die es nicht aufweisen. Es ist keine dokumentierten Parameter, und in der Tat nur um die Optimierung für einige Benchmarks sein kann. Meine Beobachtung ist, dass es geholfen, aber ich würde ein wichtiges System nicht bauen auf ihr basiert.

Zwei Dinge vorsichtig sein:

  1. Verwenden Sie new String("abc") Konstruktor nicht, nur den wörtlichen "abc" verwenden.
  2. Lernen intern zu verwenden ( ) Methode in String-Klasse. Vor allem, wenn Zeichenkette zusammen, oder wenn die Umwandlung char Array / Byte-Array / etc zu einem String verketten.

intern() kehrt immer Strings, die gebündelt werden.

Wenn Ihre identischen Strings aus einem festen Satz von möglichen Werten kommen, dann eine typsichere Enumeration ist, was Sie hier wollen. Nicht nur wird es Ihre String Zahl reduzieren, aber es wird für eine solidere Anwendung machen. Ihre ganze App wird diesen String wissen hat Semantik an mich, vielleicht sogar einige bequemen Methoden.

Meine Lieblinge Optimierungen sind immer diejenigen, die als Voraussetzung für den Code verteidigt werden können besser , nicht nur schneller. Und 9 mal von 10, einen String mit einem konkreten Typ führt zu mehr richtig und selbstdokumentiere Code zu ersetzen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top