Weiter zum Inhalt

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.

Übung

{ 3 } Comments

  1. jhb | 18. Juni 2010 um 18:16 | Permalink

    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.

  2. Stefan Kiesel | 20. Juni 2010 um 11:33 | Permalink

    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

  3. Britta | 22. Juli 2010 um 12:14 | Permalink

    Das mit der Pool-Methode in Java ist mir neu, wieder was dazu gelernt :)

{ 2 } Trackbacks

  1. [...] interessant: Java Blog Buch : 03.02 Strings vergleichen __________________ #fachinformatiker.de im IRC | http://wiki.lupo49.de/ | IT staff – Getting [...]

  2. [...] is empty");} [/CODE] nicht dasselbe Ergebnis liefert findet man hier: Java Blog Buch : 03.02 Strings vergleichen Die einzige Sache die sich mir noch nicht erschlossen hat, ist wieso die Datenbank ein leeres [...]

Kommentar verfassen

Dein E-Mail wird nicht veröffentlicht oder weitergegeben. Pflichtfelder sind mit * markiert.
*