2010-10-27 6 views
13

Wie bereits erwähnt, vergleicht der Operator == Objektreferenzen, um zu überprüfen, ob sie sich auf dasselbe Objekt auf einem Heap beziehen. Wenn ja, warum bekomme ich das "Equal" für diesen Code?Wenn == Verweise in Java vergleicht, warum bewertet es mit diesen Zeichenfolgen als wahr?

public class Salmon { 
    public static void main(String[] args) { 

     String str1 = "Str1"; 
     String str2 = "Str1"; 

     if (str1 == str2) { 
      System.out.println("Equal"); 
     } else { 
      System.out.println("Not equal"); 
     } 
    } 
} 
+1

Sind Sie sicher, dass Sie '==' oder '=' ?? –

+0

Geändert ein Codebeispiel, sorry – Eugene

+1

Stellen Sie sicher, dass die Sprache JAVA ist. Andere Sprachen haben andere Implementierungen. Was auch immer der == Operator für .net ist. – CodingBarfield

Antwort

37

Das Programm wird Equal drucken. (zumindest mit der Sun Hotspot und Sonnen Javac.) Hier wird gezeigt, auf http://ideone.com/8UrRrk

Dies ist aufgrund der Tatsache, dass die String-wörtlicher Konstanten in einem Zeichenfolge-Pool gespeichert werden und String verweist kann wiederverwendet werden .

Weiterführende Literatur:


Dies ist jedoch:

public class Salmon { 
    public static void main(String[] args) { 

     String str1 = "Str1"; 
     String str2 = new String("Str1"); 

     if (str1 == str2) { 
      System.out.println("Equal"); 
     } else { 
      System.out.println("Not equal"); 
     } 
    } 
} 

drucktseit new ist garantiert, um eine neue Referenz einzuführen.

Also, Faustregel: Vergleichen Sie immer Zeichenfolgen mit der equals Methode.

+0

+1 für die Verknüpfung mit ideone.com einbetten. Ich wollte so lange eine Webapp haben. Selbst daran gedacht, es selbst zu schreiben, aber da ist es. –

+3

Der Vollständigkeit halber 'neue Zeichenkette (" Str1 "). Intern()' druckt "Gleich" auch :) – OscarRyz

+0

@OscarRyz, Guter Punkt. Vielen Dank! :-) – aioobe

3

Dieser Code wird Equal nicht gedruckt.
Aber wenn die zwei Saiten die gleichen wären, wäre dieser Fall speziell.

Jetzt, wo Sie Ihren Code aktualisiert haben, ist es der Fall:

Eine einfache (aber nicht ganz genau) Erklärung ist, dass der Compiler sehen, dass die beiden Strings gleich sind und so etwas wie:

String str1 = "Str1"; 
String str2 = str1; 

Was hier wirklich passiert ist, dass der Compiler die Zeichenkette sehen und es in der „Stringliteral Pool“ setzen.

Da ein String nicht geändert werden kann (er ist unveränderlich), werden die Literalwerte von Strings (die beim Übersetzen gefunden werden) in einen "Pool" gestellt.
Auf diese Weise wird der Speicher nicht verschwendet, um "Str1" und "Str1" zwei Mal zu speichern, wenn zwei verschiedene Literalzeichenfolgen denselben Inhalt haben (wie in diesem speziellen Fall).

+0

Ich bin Entschuldigung, ich habe dem Codebeispiel Korrekturen hinzugefügt. – Eugene

3

Java speichert alle Zeichenfolgen in einer Zeichenfolgentabelle intern während eines Laufs. Die Verweise auf die beiden Zeichenfolgen sind identisch, da sie im Speicher an derselben Stelle gespeichert sind. Daher Equal.

Ihre Aussage ist richtig, dass == Objektreferenzen vergleicht. Versuchen Sie dasselbe mit jeder anderen Klasse, aber Strings und Sie werden nicht das gleiche Ergebnis erhalten.

+0

Es tut? Kannst du mir einen Hinweis darauf geben, diese Behauptung zurückzuweisen? –

+1

aioobe gibt eine bessere Erklärung, da dieses Verhalten nicht garantiert ist. Und es gilt auch nur für String-Literale, nicht für jede Zeichenfolge in einem Programm. – Joey

+2

Aus den Java-API-Dokumenten: "Alle literalen Zeichenfolgen und konstanten Konstantenausdrücke werden intern gespeichert." Siehe http://download.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#intern%28%29 Beachten Sie, dass nur konstante Strings automatisch interniert werden. Sie können dynamisch erstellte Strings internieren, indem Sie String.intern() –

0

Kommentare oben haben es ziemlich gut zusammengefasst.

Ich habe keine Java-Umgebung zur Hand, aber der Versuch, die folgenden Dinge für Sie zu klären (hoffentlich funktioniert das, wie ich es erwarte).

String str1 = "Str1"; 
String str2 = "Str"; str2 += "1"; 

Sollte drucken jetzt nicht gleich

2

Menschen, Sie zu vergessen, dass der Prozess Literalzeichenfolgen im Pool des Vergebens ist „Internierung“ genannt. Die Klasse String hat eine Methode namens intern(). Diese Methode fügt eine Zeichenfolge in den Pool ein, auch wenn sie anfangs nicht im Pool ist (nicht literal). Dies bedeutet, dass Code wie folgt:

String a = "hello"; 
String b = new String("hello"); 
b = b.intern(); 

System.out.println(a == b); 

gedruckt wird "true". Nun, warum sollte jemand das brauchen? Wie Sie sich vorstellen können, kann der String-Vergleich a.equals(b) lange dauern, wenn die Strings die gleiche Länge haben, sich aber nahe am Ende unterscheiden. (Schauen Sie sich einfach den .equals() Quellcode an.).

Der direkte Vergleich von Referenzen ist jedoch der gleiche wie der Vergleich von Ganzzahlen (Zeiger in C-Sprache), die fast augenblicklich ist.

Also, was gibt dir das? Geschwindigkeit. Wenn Sie die gleichen Strings viele, viele Male vergleichen müssen, wird Ihre Programmleistung enorm profitieren, wenn Sie diese Strings internieren. Wenn Sie jedoch Strings nur einmal vergleichen, wird es keinen Leistungsgewinn geben, da der Internierungsprozess selbst equals() verwendet.

Ich hoffe, dies erklärt dies.

danke

Verwandte Themen