Zeitpunkt der Strings-Erstellung in Java

8

Ich schreibe eine App für J2ME-Geräte und kümmere mich sehr um unnötige String-Erstellung. Da die Arbeit mit Strings integriert ist, d. H. Es ist nicht notwendig, sie explizit zu erstellen, bin ich nicht sicher, ob ich es richtig verstehe.

Wenn Sie zum Beispiel einen String zurückgeben (indem Sie einfach die Anführungszeichen verwenden), wird der String erzeugt, wenn er zurückgegeben wird, d. h. wenn mehrere Rückgabeanweisungen unterschiedliche Strings zurückgeben, wird nur einer erstellt. Ist das richtig?

Auch wenn Strings zum Drucken von Nachrichten mit Ausnahmen verwendet werden, werden diese Strings niemals erstellt, wenn die Ausnahme nicht ausgelöst wird, oder?

Entschuldigen Sie die Störung mit solch einer neuen Frage.

    
Albus Dumbledore 12.08.2010, 09:11
quelle

6 Antworten

4

Ich bin mir über die Antworten, die Sie bisher erhalten haben, überhaupt nicht sicher. Wenn Sie nur sind, geben Sie ein Zeichenfolgenliteral zurück, z. B.

%Vor%

Dann werden diese Werte in die Klassendatei eingebettet. Die JVM stellt sicher, dass immer nur eine Instanz dieser Zeichenkette erstellt wird (aus dem Literal) - aber ich glaube nicht, dass es eine Garantie dafür gibt, dass keine Zeichenketten für alle Konstanten in einer Klasse erstellt werden wenn die Klasse selbst geladen ist.

Da die Zeichenkette nur einmal einmal (pro Zeichenkettenkonstante) erstellt wird, ist es wahrscheinlich kein Problem.

Nun, wenn Ihr Code tatsächlich mehr wie folgt lautet:

%Vor%

Dann wird dynamisch eine Zeichenkette erzeugt - aber es wird nur erzeugt, wenn die return-Anweisung tatsächlich getroffen wird.

    
Jon Skeet 12.08.2010, 09:29
quelle
2

Die Antwort ist ein bisschen komplizierter als einige der anderen Antworten vorschlagen.

  • Der String-Wert, der einem String-Literal in Ihrem Quellcode entspricht, wird einmalig beim Laden der Klasse erstellt. Darüber hinaus werden diese Strings automatisch "interniert", dh wenn dasselbe Literal an mehr als einer Stelle in einer Klasse erscheint, wird nur eine Kopie des Strings beibehalten . (Alle anderen Kopien, wenn sie erstellt wurden wird Müll gesammelt.)

  • Wenn die Anwendung new String(...) aufruft, wenn sie einen String-Verkettungsausdruck (dh den Operator + ) auswertet oder wenn sie eine der vielen Bibliotheksmethoden aufruft, die Strings unter der Haube erzeugen, eine neue Zeichenfolge wird erstellt.

Also, um Ihre Fragen zu beantworten:

1 - Das Folgende wird überhaupt keinen String erzeugen. Stattdessen wird ein String zurückgegeben, der beim Laden der Klasse erstellt wurde:

%Vor%

2 - Im Folgenden werden zwei Strings erstellt. Zuerst wird es someObject.toString () aufrufen, dann verkettet es das mit dem Literal, um einen anderen String zu geben.

%Vor%

3 - Folgendes wird keinen String erzeugen; siehe 1.

%Vor%

4 - Im Folgenden werden zwei Strings erstellt, wenn es ausgeführt wird; siehe 2.

%Vor%

(Eigentlich 3 und 4 beschönigen die Tatsache, dass das Erstellen einer Ausnahme dazu führt, dass Details des Aufruf-Stacks des aktuellen Threads erfasst werden, und diese Details beinhalten einen Methodennamen, Klassennamen und Dateinamen für jeden Frame. Er ist nicht spezifiziert wenn die Strings, die diese Dinge repräsentieren, tatsächlich erzeugt werden oder interniert werden, also ist es möglich, dass das Erzeugen eines Exception-Objekts die Erzeugung einer Anzahl von Strings auslöst.)

    
Stephen C 12.08.2010 09:36
quelle
1
  1. Richtig
  2. Richtig
Gopi 12.08.2010 09:15
quelle
1

Ja. Wenn ein Ausdruck, der eine Instanz entweder durch Aufrufen eines Konstruktors erstellt, oder wenn (für Strings) das Auswerten eines Literals nicht ausgeführt wird, wird nichts erstellt.

Und weiter, machen Compiler einige Optimierungen. String-Objekte, die auf String-Literalen basieren, werden nur einmal erstellt und anschließend intern gespeichert. wie hier:

%Vor%

Das JVMS hat eine andere "Meinung":

  

Eine neue Klasseninstanz kann implizit in den folgenden Situationen erstellt werden:

     
  • Das Laden einer Klasse oder einer Schnittstelle, die ein String-Literal enthält, kann ein neues String-Objekt (§2.4.8) zur Darstellung dieses Literals erzeugen. Dies kann nicht auftreten, wenn das Objekt "a String" bereits erstellt wurde, um ein vorheriges Vorkommen dieses Literals darzustellen, oder wenn die Methode "String.intern" für ein String-Objekt aufgerufen wurde, das die gleiche Zeichenfolge wie das Literal darstellt.
  •   

Das obige Beispiel ist also falsch (ich lerne jeden Tag etwas Neues). Die VM überprüft während des Klassenladens, ob "Hello" erstellt werden muss oder nicht (und erstellt eine String-Instanz, falls sie noch nicht existiert).

Nun verstehe ich, dass die VM eine String-Instanz für jedes eindeutige String-Literal (auf Byte-Code-Ebene!) erstellt, unabhängig davon, ob sie verwendet wird oder nicht.

( auf Byte-Code-Ebene , weil Compiler die Verkettungen von String-Literalen zu einem Literal optimieren können, wie: der Ausdruck "one"+"two" wird zu "onetwo" kompiliert)

    
Andreas_D 12.08.2010 09:31
quelle
0

Strings (und andere Objekte) werden nur erzeugt, wenn Sie sie aufrufen.

Also, um Ihre Fragen zu beantworten:

  1. Ja, nur der String, der zurückgegeben wird, wird erstellt
  2. Ja, nur wenn die Ausnahme ausgelöst wird, wird dieser String erstellt
Molske 12.08.2010 09:15
quelle
0

Das Hauptkonzept hier ist, dass die Heap-Zuweisung (was Sie sagen, Erstellung) für jeden String oder in allgemeineren Begriffen für jedes Objekt nicht stattfindet, bis Ihr Logikfluss den Interpreter veranlasst, diese Zeile kompilierten Codes auszuführen.

    
sky 12.08.2010 10:28
quelle

Tags und Links