2010-10-01 7 views
13

I-Code haben wie folgt:Ist es immer eine schlechte Idee + verwenden Strings verketten

String s = ""; 
for (My my : myList) { 
    s += my.getX(); 
} 

Findbugs immer meldet Fehler, wenn ich dies tun.

+1

ist getX(); eine Zeichenfolge zurückgeben? –

+0

Ich glaube nicht, dass es "immer" schlecht ist. Aber häufiger gibt es dann keine Alternativen, die besser geeignet sind. – decompiled

+6

Es ist definitiv nicht _always bad_, Verkettung mit + zu verwenden. Es ist jedoch schlecht, wenn Sie einen solchen Loop machen. – ColinD

Antwort

21

würde ich + verwenden, wenn Sie manuell verketten,

String word = "Hello"; 
word += " World!"; 

Wenn Sie jedoch iterieren und verketten Ich würde StringBuilder vorschlagen,

StringBuilder sb = new StringBuilder(); 
for (My my : myList) { 
    sb.append(my.getX()); 
} 
+7

+1 zu lesen - es ist eine Verkettung * in einer Schleife *, die Sie im Allgemeinen vermeiden sollten. –

+0

Ein anderer Punkt: es kann tatsächlich _better_ sein, + in einigen Fällen zu verwenden, wenn Zeichenfolgenliterale verkettet werden, da eine Reihe von verketteten Literalen als eine Zeichenfolge kompiliert wird. Ich bin nicht positiv, da es auf mehrere Zeilen aufgeteilt ist, aber ich denke, der Compiler würde das auf 'String word =" Hello World! "' Optimieren. – ColinD

+0

Es ist OK, die Verkettung so zu verwenden, wenn Sie sicher sind, dass Ihre Anwendung nie lokalisiert wird. Wenn Sie vorhaben, es in eine Fremdsprache zu übersetzen, werden Sie einen Lokalisierbarkeitsfehler haben. –

8

Das String-Objekt ist in Java unveränderlich. Jedes + bedeutet ein anderes Objekt. Sie können StringBuffer verwenden, um die Anzahl der erstellten Objekte zu minimieren.

+7

Java übersetzt die Verkettung mit +, um einen 'StringBuilder' zu verwenden. Sie müssen den 'StringBuilder' nur dann selbst verwenden, wenn Sie eine Zeichenfolge mit einer Reihe von Methodenaufrufen oder ähnlichem loopen oder erstellen. Außerdem hat 'StringBuffer' einen Thread-Sicherheitsaufwand, den Sie normalerweise nicht benötigen, daher ist' StringBuilder' im Allgemeinen eine bessere Wahl. – ColinD

+5

_Tony huscht weg, um über StringBuilder_ –

3

Der Compiler etwas, was wie

optimieren

"foo" + "bar"

zu

StringBuilder s1 = new StringBuilder(); s1.append ("foo"). Append ("bar");

Dies ist jedoch immer noch suboptimal, da es mit einer Standardgröße von 16 beginnt. Wie bei vielen Dingen sollten Sie jedoch Ihre größten Flaschenhälse finden und sich in der Liste nach unten arbeiten. Es tut nicht weh, in der Gewohnheit zu sein, ein SB-Muster von dem Get-Go zu verwenden, besonders wenn Sie in der Lage sind, eine optimale Initialisierungsgröße zu berechnen.

+0

eigentlich kann der * Compiler * dies nur auf "foobar" '... +1 für das Auffinden des Engpasses optimieren –

3

Vorzeitige Optimierung kann sowohl schlecht als auch oft die Lesbarkeit beeinträchtigen und ist normalerweise völlig unnötig. Verwenden Sie +, wenn es lesbarer ist, es sei denn, Sie haben tatsächlich ein vorrangiges Problem.

3

Es ist nicht "immer schlecht", "+" zu verwenden. Die Verwendung von StringBuffer überall kann Code sehr umfangreich machen.

Wenn jemand eine Menge "+" mitten in eine intensive, zeitkritische Schleife steckt, wäre ich genervt. Wenn jemand eine Menge "+" in ein selten verwendetes Stück Code steckt, wäre mir das egal.

1

würde ich sagen, Verwendung und in den folgenden:

String c = "a" + "b"

und überall sonst Stringbuilder-Klasse verwenden. Wie bereits im ersten Fall erwähnt, wird es vom Compiler optimiert und besser lesbar.

4

Jedes Mal, wenn Sie string+=string tun, ruft es Verfahren wie folgt aus:

private String(String s1, String s2) { 
    if (s1 == null) { 
     s1 = "null"; 
    } 
    if (s2 == null) { 
     s2 = "null"; 
    } 
    count = s1.count + s2.count; 
    value = new char[count]; 
    offset = 0; 
    System.arraycopy(s1.value, s1.offset, value, 0, s1.count); 
    System.arraycopy(s2.value, s2.offset, value, s1.count, s2.count); 
} 

Bei String, kommt es zu:

final void append0(String string) { 
    if (string == null) { 
     appendNull(); 
     return; 
    } 
    int adding = string.length(); 
    int newSize = count + adding; 
    if (newSize > value.length) { 
     enlargeBuffer(newSize); 
    } 
    string.getChars(0, adding, value, count); 
    count = newSize; 
} 

Wie man deutlich abschließen kann, string + string schafft eine Menge Overhead, und meiner Meinung nach sollte vermieden werden, wenn möglich.Wenn Sie denken, mit String sperrig ist oder zu lange können Sie nur eine Methode machen und es indirekt verwenden, wie:

public static String scat(String... vargs) { 
    StringBuilder sb = new StringBuilder(); 

    for (String str : vargs) 
     sb.append(str); 

    return sb.toString(); 
} 

Und verwenden Sie es mögen:

String abcd = scat("a","b","c","d"); 

In C# ich seine über gesagt bin genauso wie string.Concat();. In Ihrem Fall wäre es klug, Überlastung für kv zu schreiben, wie:

public static String scat(Collection<?> vargs) { 
    StringBuilder sb = new StringBuilder(); 

    for (Object str : vargs) 
     sb.append(str); 

    return sb.toString(); 
} 

Dann können Sie es mit rufen:

result = scat(myList) 
1

Einer der Gründe, warum FindBugs über die Verwendung von Verkettungsoperator argumentieren sollte (sein es "+" oder "+ =") ist Lokalisierbarkeit. Im Beispiel gab man es nicht so offensichtlich ist, aber im Fall des folgenden Codes ist:

String result = "Scanning found " + Integer.toString(numberOfViruses) + " viruses"; 

Wenn dies ein wenig vertraut aussieht, müssen Sie Ihren Programmierstil ändern. Das Problem ist, dass es auf Englisch gut klingen wird, aber es könnte ein Albtraum für Übersetzer sein. Das liegt nur daran, dass Sie nicht garantieren können, dass die Reihenfolge des Satzes nach der Übersetzung immer noch dieselbe ist - manche Sprachen werden in "1 blah blah" übersetzt, einige in "blah blah 3". In solchen Fällen sollten Sie immer MessageFormat.format() verwenden, um zusammengesetzte Sätze zu erstellen, und den Verkettungsoperator zu verwenden, ist eindeutig ein Internationalisierungsfehler.

BTW. Ich habe hier einen weiteren Fehler gemacht, könntest du es entdecken?

0

Die Laufzeit der Verkettung zweier Strings ist proportional zur Länge der Strings. Wenn es in einer Schleife verwendet wird, wird die Laufzeit immer größer. Also, wenn Verkettung in einer Schleife benötigt wird, ist es besser, StringBuilder wie Anthony vorgeschlagen.

Verwandte Themen