# Stringvergleich



## java.coder (17. Jul 2007)

```
class Stringvergleich
{
  String s = "vergleich";
  String m = "vergleich";
  
  public Stringvergleich()
  {
    if(s.compareTo(m) == 0)
      System.out.println("s.compareTo(m) == 0");
    if(s.equals(m))
      System.out.println("s.equals(m)");
    if(s == m)
      System.out.println("s == m");
  }
  
  public static void main(String[] argv)
  {
    new Stringvergleich();
  }
}
```

Die Ausgabe ist 3 mal das was im System.out.println drinsteckt. Heißt das nun, dass die Zeiger des Strings (Objekte?) gleich sind? Das kann aber doch nicht sein, denn der Inhalt dieser Strings sind gleich, oder denke ich da zu kompliziert.

Und welche dieser 3 sollte ich generell für Stringvergleiche hernehmen (um auf Gleichheit zu überprüfen)?


----------



## Wildcard (17. Jul 2007)

equals vegleicht den Inhalt, compareTo ob das eine größer als das andere ist und == ob es sich um ein identisches Objekt handelt.


----------



## hansz (18. Jul 2007)

Das kurze Listing zeigt ein Beispiel zu equals und dem "=="-Operator:



> ```
> /* Test.java */
> 
> public class Test {
> ...




Innerhalb von String.java (im JDK) wird die Methode compareTo wie folgt definiert: :autsch: 



> /**
> * Compares two strings lexicographically.
> * The comparison is based on the Unicode value of each character in
> * the strings. The character sequence represented by this
> ...




Gruß,
hansz


----------



## byte (18. Jul 2007)

java.coder hat gesagt.:
			
		

> Und welche dieser 3 sollte ich generell für Stringvergleiche hernehmen (um auf Gleichheit zu überprüfen)?



Du solltest Strings auf Gleichheit immer mit equals vergleichen. In diesem Fall liefert == zwar auch das "richtige" Ergebnis, das liegt aber nur daran, dass Du sie per String-Literal erzeugst. Das heisst, beim zweiten String merkt er, dass dieser schon existiert und setzt ne Referenz drauf. Wenn Du die Strings stattdessen mit new erzeugst, solltest Du an dieser Stelle ein anderes Ergebnis bekommen.

Du brauchst Dir aber prinzipiell nur merken: Inhaltliche Gleichheit immer mit equals, == nur bei Objektgleichheit und compareTo bei größer/kleiner Vergleich.


----------



## Guest (18. Jul 2007)

java.coder hat gesagt.:
			
		

> Heißt das nun, dass die Zeiger des Strings (Objekte?) gleich sind?


Die zwei Referenzvariablen namens s und m zeigen beide auf das selbe unbenannte String-Objekt, welches den Inhalt "vergleich" hat. Das liegt daran, dass String-Objekte, welche durch gleiche Literalausdrücke erzeugt werden, nach Möglichkeit zusammengefasst werden (d.h. wenn die Zeichenketten übereinstimmen). Das geht sogar über Package-Grenzen hinweg.



			
				java.coder hat gesagt.:
			
		

> Das kann aber doch nicht sein, denn der Inhalt dieser Strings sind gleich, oder denke ich da zu kompliziert.


Identität und Gleichheit existieren nicht orthogonal zueinander. Es gibt folgende Beziehung zwischen ihnen:

identisch => gleich

s und m zeigen auf das SELBE String-Objekt. Das impliziert, dass equals true zurückliefern MUSS, denn schliesslich vergleichst Du ein String-Objekt mit sich selbst. Anderes Beispiel: Wenn Du Thomas fragst, ob er die gleiche Augenfarbe hat wie Thomas, dann wird er IMMER ja antworten.

a.equals(a) muss immer true zurückliefern, also auch a.equals(b) falls a == b. Bezogen auf Thomas: Wenn Du Thomas' Mutter fragst, ob ihr Sohn die gleiche Augenfarbe hat wie der Sohn ihres Mannes, was wird sie dann antworten? 



			
				java.coder hat gesagt.:
			
		

> Und welche dieser 3 sollte ich generell für Stringvergleiche hernehmen (um auf Gleichheit zu überprüfen)?


Falls Du den Inhalt der String-Objekte miteinander vergleichen möchtest, dann nimm IMMER die equals-Methode. Der Trick, dass gleiche Stringinhalte in gleichen String-Objekten resultieren, funktioniert nur für die zur Kompilierzeit konstanten Stringliterale. Wenn Du dagegen z.B. einen Benutzer zur Laufzeit aufforderst, etwas einzugeben (oder wenn Du aus einer Datei liest oder oder oder...), dann wird daraus IMMER ein neues String-Objekt, unabhängig davon, ob es bereits ein anderes mit dem gleichen Inhalt gibt.

In Deinem Beispiel gibt es übrigens keinen Grund, ein Objekt von Stringvergleich zu erzeugen und dann im Konstruktor die Arbeit durchzuführen. Mach es doch gleich in der main-Methode, das ist konzeptionell sauberer:


```
class Stringvergleich
{
  public static void main(String[] argv)
  {
    String s = "vergleich";
    String m = "vergleich";
    if(s.compareTo(m) == 0)
      System.out.println("s.compareTo(m) == 0");
    if(s.equals(m))
      System.out.println("s.equals(m)");
    if(s == m)
      System.out.println("s == m");
  }
}
```

Fred


----------

