Frage

Das habe ich oft gefragt, gibt es ein Performance-Kosten einen String über mehrere Zeilen aufgeteilt Lesbarkeit zu erhöhen, wenn zunächst einen Wert in einem String zuweisen. Ich weiß, dass Strings sind unveränderlich und damit eine neue Zeichenfolge muss jedes Mal erstellt werden. Außerdem ist die Leistungskosten tatsächlich irrelevant dank der heutigen wirklich schnelle Hardware (es sei denn, Sie in irgendeiner teuflischen Schleife sind). So zum Beispiel:

String newString = "This is a really long long long long long" +
    " long long long long long long long long long long long long " +
    " long long long long long long long long long string for example.";

Wie funktionieren die JVM oder .NET-Compiler und andere Optimierungen damit umgehen. Wird es eine einzelne Zeichenfolge erstellen? Oder wird es schaffen 1 string dann ein neuer Wert verketten und dann ein anderer die Werte verketten wieder?

Dies ist für meine eigene Neugier.

War es hilfreich?

Lösung

Dies wird durch das C # spec garantiert zum Erstellen der Zeichenfolge in einem einzigen wörtlichen identisch zu sein, denn es ist ein Kompilierung-Konstante. Aus dem Bereich 7.18 der C # 3 spec:

  

Jedes Mal, wenn ein Ausdruck des erfüllt   oben aufgeführten Anforderungen, die   Ausdruck wird ausgewertet bei   Kompilierung der Zeit. Dies gilt auch, wenn die   Ausdruck ist ein Unterexpression eines   größer Ausdruck, der enthält   nicht konstante Konstrukte.

(Siehe Spezifikation für die genauen Details von „die oben aufgeführten Anforderungen“:)

Die Java Language Specification gibt es am unteren Rand der Abschnitt 3.10.5 :

  

Strings durch Konstante berechnet   Ausdrücke (§15.28) berechnet auf   Kompilierung und dann behandelt, als ob   sie waren Literale.

Andere Tipps

Ja, in Java, wird der Compiler die String in eine konstante drehen.

class LongLongString
{
    public LongLongString()
    {
        String newString = "This is a really long long long long long" +
            " long long long long long long long long long long long long " +
            " long long long long long long long long long string for example.";
    }

    public static void main(String[] args)
    {
        new LongLongString();
    }
}

Ist kompiliert in:

Compiled from "LongLongString.java"
class LongLongString extends java.lang.Object{
public LongLongString();
  Code:
   0:   aload_0
   1:   invokespecial   #1; //Method java/lang/Object."<init>":()V
   4:   ldc #2; //String This is a really long long long long long long long long long long long long long long long long long  long long long long long long long long long string for example.
   6:   astore_1
   7:   return

public static void main(java.lang.String[]);
  Code:
   0:   new #3; //class LongLongString
   3:   dup
   4:   invokespecial   #4; //Method "<init>":()V
   7:   pop
   8:   return

}

Wie zu sehen ist, eine einzelne Zeile in Zeile 4 geladen in, anstatt mehr Instanzen String werden geladen in.

Edit: Die Quelldatei kompiliert wurde javac Version 1.6.0_06 verwenden. Mit Blick auf der Java Language Specification, Third Edition , (und derselbe Abschnitt in Jon Skeet Antwort ), ich war nicht in der Lage für jeden Hinweis zu finden, ob ein Compiler eine mehrzeilige String in einem einzigen String verketten sollte, so ist dieses Verhalten wahrscheinlich Compiler Implementierung spezifisch.

Testen Sie diese für sich selbst. In C # -Code (entspricht Java funktionieren würde auch):

string x = "A" + "B" + "C";
string y = "ABC";

bool same = object.ReferenceEquals(x, y); // true

Sie werden sehen, dass das Ergebnis true.

Als Nebenwirkung, werden Sie sehen, dass die Zeichenfolge auch in der Laufzeit der String-Pool interniert wird:

bool interned = object.ReferenceEquals(x, string.Intern(x)); // true

Keine Leistung Kompromiss. Compiler-Optimierung fusionieren, das zu einem einzelnen String (zumindest in Java).

Soweit ich mich erinnern kann, wird dies mehrere Strings nicht schaffen, nur die eine.

Die äquivalente .NET IL ergänzen coobird Antwort :

Für C # -Code:

string s = "This is a really long long long long long" +
    " long long long long long long long long long long long long " +
    " long long long long long long long long long string for example.";
Console.WriteLine(s);

Eine Debug-Kompilierung erzeugt:

.method public hidebysig static void Main(string[] args) cil managed
{
  .custom instance void [mscorlib]System.STAThreadAttribute::.ctor()
  .maxstack 1
  .locals init (
      [0] string str)
  L_0000: ldstr "This is a really long long long long long long long long long long long long long long long long long  long long long long long long long long long string for example."
  L_0005: stloc.0 
  L_0006: ldloc.0 
  L_0007: call void [mscorlib]System.Console::WriteLine(string)
  L_000c: ret 
}

So, wie Sie sehen können, ist es eine Saite.

Solange alle Saiten konstant sind (wie sie in Ihrem Beispiel sind), in Java (und ich denke, C #) der Compiler wandelt diese in einem einzigen String.

Sie erhalten nur Probleme mit der Leistung +, wenn Sie eine Menge von dynamischen Streichern, wie in einer Schleife verketten. In diesem Fall wird ein String oder String verwenden.

Disclaimer: Dies gilt für Java. Ich würde seine wahre für c #

übernehmen

wird nicht nur einen einzigen String erstellen JavaC aber die JVM wird ein String für alle anderen String verwendet werden, die den gleichen Text enthalten.

String a = "He" + "llo th"+ "ere";
String b = "Hell" + "o the"+ "re";
String c = "Hello" +" "+"there";
assert a == b; // these are the same String object.
assert a == c; // these are the same String object.

. Hinweis: werden sie das gleiche String-Objekt zur Laufzeit, auch wenn sie in verschiedenen Klassen in verschiedenen JARS sind, durch verschiedene Compiler kompiliert

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