2015-07-13 12 views
6

Ich verstehe nicht, warum System.out.println (Name) Ausgänge Sam ohne durch die Methode der concat-Funktion beeinträchtigt zu werden, während System.out.println (Namen) Ausgaben Sam4 als Ergebnis der Append-Methode der Methode. Warum ist StringBuilder betroffen und nicht String? Normalerweise wirkt sich das Aufrufen von Methoden auf einen Verweis auf ein Objekt auf den Aufrufer aus, daher verstehe ich nicht, warum das String-Ergebnis unverändert bleibt. Vielen Dank im VorausPass-by-Wert (String vs String)

public static String speak(String name) { 
    name = name.concat("4"); 
    return name; 
} 

public static StringBuilder test(StringBuilder names) { 
    names = names.append("4"); 
    return names; 
} 

public static void main(String[] args) { 
    String name = "Sam"; 
    speak(name); 
    System.out.println(name); //Sam 
    StringBuilder names = new StringBuilder("Sam"); 
    test(names); 
    System.out.println(names); //Sam4 
} 
+0

Viele Antworten hier, im Grunde sagen alle das Gleiche. Schwer zu wählen, um zu upvote :) –

+2

@ArnaudDenoyelle Zum Glück müssen Sie nicht nur eine wählen;) –

+0

@ArnaudDenoyelle wie Mark Rotteveel sagte, Helenesh ist derjenige, der diese schwierige Entscheidung treffen muss;) – Karthik

Antwort

9

Denn wenn man speak(name);, innen sprechen anrufen, wenn Sie

name = name.concat("4"); 

tun schafft es ein neues Objekt, weil String s unveränderlich ist. Wenn Sie die ursprüngliche Zeichenfolge ändern, wird ein neues Objekt erstellt. Ich stimme zu, dass Sie es zurückgeben, aber nicht erfassen.

Also im Wesentlichen, was Sie tun, ist:

name(new) = name(original) + '4'; // but you should notice that both the names are different objects. 

versuchen

String name = "Sam"; 
name = speak(name); 

Natürlich jetzt denke ich, gibt es keine Notwendigkeit zu erklären, warum es mit StringBuilder Arbeit ist, es sei denn, wenn Sie nicht wissen, dass StringBuilder veränderbar ist.

+0

"es schafft eine neue Objekt, weil Strings unveränderlich sind. " Es gibt kein Konzept der "Veränderlichkeit" in der Sprache. Es gibt ein neues Objekt zurück, weil die Methode dafür dokumentiert ist. Es ändert das Objekt, das es aufgerufen wird, nicht erneut, da dies für die Methode dokumentiert ist. – newacct

+1

@newacct Sorry Sir, ich bin sicher, ich weiß nicht so viel wie du, aber ich dachte OP wäre nicht glücklich, wenn ich sage "Es gibt ein neues Objekt zurück, weil es dokumentiert ist, dies zu tun". Deshalb wollte ich dahinter ein paar Überlegungen anstellen. – Karthik

+0

Aber wir sagen nur, dass die Klasse "unveränderbar" ist, nur weil alle ihre Methoden dokumentiert sind, um sie nicht zu modifizieren. Es wäre also ein Zirkelschluss zu sagen, dass die Methoden es nicht modifizieren, weil es unveränderlich ist. – newacct

3

Wenn Sie speak(name) aufrufen, berechnet es den neuen Wert, verwirft ihn jedoch.

Wenn Sie es mit

name = speak(name); 

das Ergebnis ersetzen wird diejenige, die Sie erwarten.

Mit dem StringBuilder, das Objekt, das Sie passieren Wandelbare: so

names.append(names); 

der Zustand des aktuellen Objekts ändert (es gibt auch einen Verweis auf das gleiche Objekt, das nur eine Bequemlichkeit ist es, Ihnen zu ermöglichen, schreibe Code wie names.append(...).append(...) etc.). Im Fall der StringBuilder hat sich das Objekt, auf das Sie verweisen, wenn Sie die Methode aufrufen, tatsächlich geändert, daher sehen Sie die Änderungen.

+0

Sie haben die Frage nicht beantwortet: Warum funktioniert es mit StringBuilder? – m0skit0

+0

Ja, stimmt. Siehe Aktualisierung. –

0

String

String ist unveränderliches Objekt (einmal nicht geändert werden erstellt werden). Das als String erstellte Objekt wird im Constant String Pool gespeichert. Jedes unveränderliche Objekt in Java ist Thread-sicher, das bedeutet, dass String auch Thread-sicher ist. String kann nicht gleichzeitig von zwei Threads verwendet werden. Einmal zugewiesene Zeichenfolge kann nicht geändert werden.

String demo = "Hallo"; // Das obige Objekt wird im konstanten String-Pool gespeichert und sein Wert kann nicht geändert werden.

demo = "Tschüss"; // neue "Bye" -String wird im Konstanten Pool erstellt und referenziert durch die Demo-Variable // "Hallo" String noch existiert in String-Konstanten-Pool und sein Wert ist nicht überschrieben, aber wir verlor Bezug auf die "Hallo" -String

String

String ist gleich der Stringbuffer, das heißt er speichert das Objekt in heap und es kann auch modifiziert werden. Der Hauptunterschied zwischen dem StringBuffer und StringBuilder ist, dass StringBuilder auch nicht threadsicher ist. StringBuilder ist schnell, da es nicht Thread-sicher ist .

Für weitere Informationen überprüfen this

Fazit: Sie brauchen nicht wieder den Wert neu zu ordnen StringBuilder wie es bereits ein Verfahren sollte Bezug Test ist sein

public static void test(StringBuilder names) { 
    names.append("4"); 
    } 

aber sprechen sollte

sein
String name = "Sam"; 
    name = speak(name); 
+0

Das ist nicht gefragt. – m0skit0

+0

Ok ich habe die Antwort aktualisiert –

3

String ist unveränderlich in Java. Sobald Sie concat Methode auf Name aufrufen. Eine neue Zeichenfolge wird erstellt und während Sie mit der alten Referenz in System.out.println(name) spielen. Wenn Sie die geänderte Zeichenfolge verwenden möchten, sollten Sie die Referenz explizit zurückgeben. Während StringBuilder ist änderbar und es gibt immer die gleiche Referenz.

3

Da String unveränderlich ist und daher nicht String#concat nicht die Original-String-Instanz ändern, es gibt nur eine neue String während die ursprüngliche unmodifizierte bleibt, während StringBuilder wandelbar ist und die Änderung der StringBuilder Instanz als Parameter übergeben reflektiert wird.

3

In Ihrer Methode speak, die concat Methode gibt einen neuen String, das ursprüngliche Objekt auf unverändert genannt wurde, ist (Strings sind unveränderlich).Wie dokumentiert:

Wenn die Länge des Arguments Zeichenfolge 0 ist, dann ist dieses String Objekt zurückgegeben. Andernfalls wird ein String-Objekt zurückgegeben, das eine Zeichenfolge darstellt, die die Verkettung der Zeichenfolge darstellt, die durch dieses String-Objekt dargestellt wird, und die Zeichenfolge, die durch die Argumentzeichenfolge dargestellt wird.

Der Aufruf name.concat("4") entspricht name + "4".

In Ihrem test Verfahren der append Methode den Inhalt der StringBuilder modifiziert. Wie dokumentiert:

Die Hauptoperationen auf einem StringBuilder sind die append und insert Methoden, die überlastet sind, um Daten von jeder Art zu akzeptieren. Jeder konvertiert ein bestimmtes Datum in eine Zeichenfolge und fügt dann die Zeichen dieser Zeichenfolge an den Zeichenfolgengenerator an oder fügt sie ein. Die Methode append fügt diese Zeichen immer am Ende des Builders hinzu. Die Methode insert fügt die Zeichen an einem bestimmten Punkt hinzu.

In Ihrem Hauptverfahren sind beide name und namesimmer noch das gleiche Objekt wie vor dem Methodenaufruf, aber der Inhalt von name ist unverändert als Strings unveränderlich sind, während der Gehalt an names wird geändert.

Wenn Sie stattdessen die Rückgabewerte beider Methoden verwendet hätten, hätten Sie das Ergebnis, das Sie erwartet haben.

4

Okay, was ist speak Methode tun?

Zunächst einmal

name.concat("4"); 

schafft neues Objekt, das zu name, verkettete mit "4" gleich ist. So

, die Linie

name = name.concat(4); 

definiert lokalen (für speak Methode) variable name.

Dann kehren Sie den Verweis auf diesen neuen Wert mit

return name; 

Also, die ursprüngliche Variable innerhalb Methode übergeben wird nicht geändert, aber die Methode zurückgibt Wert geändert.

In der test Methode ändern Sie tatsächlich Variable ohne Änderung der Referenz (die StringBuilder Klasse ist veränderbar, so variabel, wenn dieser Typ geändert werden kann).

Dann können wir sehen, eine andere Frage entsteht: Warum StringBuilder.append Wert zurückgibt, wo es redundant erscheinen kann.Die Antwort auf diese Frage liegt in der Beschreibung des "Builder" -Musters, für das es die übliche Art ist, Modifikationsmethoden zu implementieren. Siehe wikipedia on Builder pattern.

2

Zunächst ist String eine unveränderliche Klasse in Java. Eine unveränderliche Klasse ist einfach eine Klasse, deren Instanzen nicht geändert werden können. Alle Informationen in einer Instanz werden beim Erstellen der Instanz initialisiert und die Informationen können nicht geändert werden.

Zweitens werden in Java Parameter durch Werte und nicht durch Referenz gesendet.

In Ihrer Methode "Test" brauchen Sie nicht names = names.append("4"), stattdessen names.append("4") wird genug sein.

Wenn Sie Java docs für String-Objekt überprüfen, werden Sie sehen, dass die meisten Methoden dort, einschließlich concat, eine neue Zeichenfolge generieren.

So auf Ausgabe Sam4 auch für die Zeichenfolge zu haben, benötigen Sie in der Hauptmethode, um diese name = speak(name) zu haben.