Warum bekomme ich beim Vergleich von Strings nach Verwendung unterschiedlicher Verkettungen in Java unterschiedliche Ergebnisse?

7

Ich habe an dem grundlegenden Java-Programm gearbeitet und ich fand sehr lustige Dinge, die ich mit euch teile. foo () gibt output (s == s1) = false und bar gibt (s == s1) = true.

Ich möchte wissen, warum das passiert.

%Vor%     
Chakravyooh 15.06.2011, 13:18
quelle

7 Antworten

16

Im letzteren Fall optimiert der Compiler die String-Verkettung. Da dies zur Kompilierzeit erfolgen kann, verweisen beide auf das gleiche konstante String-Objekt.

Im ersten Fall kann der Aufruf length() während der Kompilierzeit nicht optimiert werden. Zur Laufzeit wird ein neues String-Objekt erzeugt, das nicht identisch mit der String-Konstante ist (aber gleich ist)

    
king_nak 15.06.2011, 13:22
quelle
3

Die String-Verkettung in bar() kann zur Kompilierzeit durchgeführt werden, da es sich um einen Ausdruck handelt, der nur aus Kompilierzeitkonstanten besteht. Obwohl die Länge der Zeichenfolge s zur Kompilierzeit offensichtlich bekannt ist, weiß der Compiler nicht, dass length() diesen bekannten Wert zurückgibt, sodass er nicht als Konstante verwendet wird.

    
Ernest Friedman-Hill 15.06.2011 13:22
quelle
2

Wenn Sie eine Codezeile wie folgt schreiben:

%Vor%

dann ist der Compiler schlau genug, um dies zu optimieren:

%Vor%

Literale Strings in Java werden in einem String-Pool verwaltet. Wenn Sie zwei Literalzeichenfolgen mit demselben Inhalt haben (z. B. s und s1 in Ihrem zweiten Beispiel), wird nur ein String -Objekt erstellt, das von den beiden Variablen gemeinsam genutzt wird.

Der Operator == in Java überprüft, ob zwei Variablen auf dasselbe Objekt verweisen. Da es im zweiten Beispiel nur ein String -Objekt gibt, ist s == s1 true .

    
Jesper 15.06.2011 13:25
quelle
2
  • String s1 = "str" + s.length();
  • String s1 = "str" + "4";

Im ersten Fall gibt s.length () einen Wert vom Typ int zurück. Im zweiten Fall ist der Typ String Obwohl die Zahl in beiden Fällen 4 ist, aber Typen sind nicht die gleichen :)

    
Palak 10.04.2015 14:04
quelle
0

Wahrscheinlich hängt es damit zusammen, dass foo () wahrscheinlich eine neue String-Instanz in s.length () (. toString ()) erzeugt, wobei bar () nur eine Konstante verkettet. Ich kenne das Wesentliche nicht, aber mein Bauchgefühl sagt mir das in dieser Richtung.

    
jpm 15.06.2011 13:24
quelle
0

Wenn ich raten müsste, würde ich sagen, dass der Java-Compiler eine Optimierung auf bar () durchführt. Bei compiletime ist klar, dass "str" ​​+ "4" durch "str4" ersetzt werden kann, das (da Strings unveränderliche Objekte sind) tatsächlich dasselbe Objekt ist wie "str4" -String, das für die s-Initialisierung verwendet wird.

>

Innerhalb von foo () ist die Optimierung nicht so stark vorwärts. Im Allgemeinen kann der Wert s1-Variable nicht sehr einfach vorhergesagt werden (in der Tat ist dieses Beispiel ziemlich genau). Also wird der Java-Compiler zwei verschiedene Variablen für s und s1 erzeugen.

Der Operator "==" vergleicht den Wert der Strings nicht! Es prüft, ob es sich um die gleichen Objekte handelt. Um die Werte der Strings zu vergleichen, verwenden Sie die Methode "equals" wie folgt:

%Vor%     
Mathias 15.06.2011 13:30
quelle
0

Sie sollten versuchen, mit der internen Methode der String-Klasse zu spielen. Java speichert so etwas wie ein Wörterbuch, in dem alle verschiedenen Zeichenfolgen gespeichert sind. Wenn Sie ein Zeichenfolgenobjekt erstellen, das zur Kompilierzeit ausgewertet werden kann, durchsucht es Java in seinem Wörterbuch. Wenn die Zeichenfolge gefunden wird, speichert sie nur eine Referenz auf diese Zeichenfolge (die tatsächlich von der internen Methode zurückgegeben wird).

Sie sollten Folgendes bemerken: "str4" == ("str" + "str4".length()) gibt false zurück, aber "str4" == ("str" + "str4".length()).intern() gibt true zurück, weil der einzige "Wrapper" ein anderes Objekt ist.

    
Jacek L. 15.06.2011 13:44
quelle

Tags und Links