03.02 Strings vergleichen
Der durchschnittliche Programmieranfänger wird davon ausgehen, dass er Zeichenketten auch einfach mit ==
wie doubles, longs, chars
, … vergleichen kann. Dies stimmt so aber nicht. Das beweist ein kleiner Test:
String str1 = new String("Hallo"); String str2 = new String("Hallo"); if (str1 == str2) { System.out.println("str1 entspricht str2"); } else { System.out.println("str1 ist anders als str2"); }
Anders als Sie erwartet haben, wird nicht „str1 entspricht str2“ ausgegeben, sondern „str1 ist anders als str2“. Aber wie kann das funktionieren? In str1
und in str2
steht doch das Selbe!? Das ist soweit auch korrekt. Ein ==
überprüft aber nicht etwa den Inhalt zweier Objekte, sondern lediglich deren Referenz. D. h. wenn beide Objekte wirklich auf denselben Platz im Arbeitsspeicher verweisen, dann ist diese Abfrage wahr. Ansonsten nicht. Auch dieser Sachverhalt lässt sich einfach demonstrieren.
String str1 = new String("Hallo"); String str2 = str1; if (str1 == str2) { System.out.println("str1 entspricht str2"); } else { System.out.println("str1 ist anders als str2"); }
Durch die Zuweisung str2 = str1
erhält str2
eine Referenz auf str1
. Somit verweisen beide Objekte auf dieselbe Stelle im Arbeitsspeicher und es wird „str1 entspricht str2“ ausgegeben.
Um zwei Zeichenketten auf inhaltliche Gleichheit zu überprüfen, wird die Methode equals()
verwendet:
String str1 = new String("Hallo"); String str2 = new String("Hallo"); if (str1.equals(str2)) { System.out.println("str1 entspricht str2"); } else { System.out.println("str1 ist anders als str2"); }
Dies gilt übrigens für alle Objekte und nicht nur für Strings. Daher merken Sie sich folgenden Satz gut: primitive Datentypen und Referenzen werden mit ==, Objekte mit equals verglichen!
Wenn Sie Zeichenketten vergleichen wollen, ohne auf Groß-/Kleinschreibung zu achten, greifen Sie auf die Methode equalsIgnoreCase()
zurück.
String str1 = new String("hAlLo"); String str2 = new String("Hallo"); if (str1.equals(str2)) { System.out.println("str1 entspricht str2"); } else if (str1.equalsIgnoreCase(str2)) { System.out.println("str1 entspricht str2 - wenn die "+ "Groß-/Kleinbuchstaben ignoriert werden."); }
String-Pool
Kompilieren Sie folgendes:
String str = "abc"; String str2 = "abc"; System.out.println(str == str2);
Zu Ihrer Verwunderung werden Sie feststellen, dass die Ausgabe dieses Codestücks true
ist. Dies liegt daran, dass Java intern einen Pool für Zeichenketten verwendet. Verwenden Sie einen String
, der bereits im Programm existiert (in diesem Fall verwendet str2
die selbe Zeichenkette wie str
), wird kein neuer String
erzeugt, sondern der String
aus dem Pool zugewiesen. Dadurch verweisen auch wirklich beide Zeichenketten auf die selbe Stelle im Pool.
Dies funktioniert aber nur, wenn der String
nicht über new
initialisiert wurde, und bereits beim Kompilieren bekannt ist (also nicht durch bspw. eine Benutzereingabe ins Programm gelangt).
String str = "abc"; String str2 = new String("abc"); System.out.println(str == str2);
Der Vergleich von Zeichenketten mit ==
ist zwar möglich, aber unsicher. Verwenden Sie deshalb immer zum Vergleich die equals
-Methode! Gleichzeitig sollten Sie bei Strings
auf das new
Schlüsselwort verzichten, da eine Verwendung der Strings aus dem Pool effizienter ist.
Wenn man sich für die Pool-Methode entscheidet und dann einen string ändert wird diese eine Pool-Variable dann separat angelegt, oder?
(davon gehe ich mal stark aus, sondern würden sich ja auch unbeteiligte Variablen ändern).
Wenn man also davon ausgehen kann, dass sich strings verändern, worin liegt dann der Vorteil?
Wenn man weiß, dass sie gleich bleiben, hätte man ja auch idR, gleich auf einen vorhanden string verwenden können.
So ganz ist mir daher der Vorteil noch nicht klar.
Hallo jhb,
man kann sich nicht „für die Pool-Methode“ entscheiden. Entweder werden Strings in den Pool gelegt, oder eben nicht. Auch ändern sich Strings nie, da Strings immutable sind (siehe 03.05 Immutability von Strings). Der Speicherort, auf dem die Variable verweist, wird bei einer Neuzuweisung (nicht Änderung, da wie gesagt nicht möglich) verändert (bzw. wenn der String schon im Pool existiert, auf diese Stelle verwiesen).
Ich denke die restlichen Fragen sind dann hinfällig? Falls nein, bitte noch einmal melden.
Gruß
Stefan
Das mit der Pool-Methode in Java ist mir neu, wieder was dazu gelernt 🙂
achso, equals… 🙂
Dankeschön!
VIELEN DANK! An dem Problem saß ich heute ziemlich lange 😉
Unglücklicherweise habe ich mir ein Minimalbeispiel ausgedacht, das so ähnlich wie das aus Ihrem String-Pool war. Da true zurückgegeben wurde, dachte ich, dass Java Strings auch mit == vergleicht…daher wunderte ich mich, warum das nicht funktioniert, wenn der eine String im Programm manuell gesetzt wird und der andere aus einer Textdatei eingelesen wird…und habe den Fehler nicht bei dem == gesucht.
Viele Grüße
Das Kapitel ist sowas von überflüssig und schlecht ausgeführt