JavaRush /Java-Blog /Random-DE /Gleicht in Java und String-Vergleich – String-Vergleich

Gleicht in Java und String-Vergleich – String-Vergleich

Veröffentlicht in der Gruppe Random-DE
Hallo! Heute werden wir über ein sehr wichtiges und interessantes Thema sprechen, nämlich den Vergleich von Objekten miteinander equal() in Java. Und tatsächlich, in welchen Fällen ist Objekt A in Java gleich Objekt B ? Gleichheits- und Zeichenfolgenvergleich - 1Versuchen wir, ein Beispiel zu schreiben:
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
Konsolenausgabe:

false
Okay, hör auf. Warum sind diese beiden Autos eigentlich nicht gleich? Wir haben ihnen die gleichen Eigenschaften gegeben, aber das Ergebnis des Vergleichs ist falsch. Die Antwort ist einfach. Der Operator ==vergleicht nicht die Eigenschaften von Objekten, sondern Links. Selbst wenn zwei Objekte 500 identische Eigenschaften haben, ist das Ergebnis des Vergleichs immer noch falsch. Schließlich car1verweisen Links car2 auf zwei verschiedene Objekte , auf zwei verschiedene Adressen. Stellen Sie sich eine Situation vor, in der Sie Menschen vergleichen. Es gibt wahrscheinlich eine Person auf der Welt, die den gleichen Namen, die gleiche Augenfarbe, das gleiche Alter, die gleiche Größe, die gleiche Haarfarbe usw. hat wie Sie. Das heißt, Sie sind sich in vielerlei Hinsicht ähnlich, aber dennoch sind Sie keine Zwillinge und vor allem nicht dieselbe Person. Gleichheits- und Zeichenfolgenvergleich - 2Der Operator wendet ungefähr die gleiche Logik an, ==wenn wir ihn zum Vergleich zweier Objekte verwenden. Was aber, wenn Sie in Ihrem Programm eine andere Logik benötigen? Wenn Ihr Programm beispielsweise eine DNA-Analyse simuliert. Sie muss den DNA-Code zweier Menschen vergleichen und feststellen, dass es sich um Zwillinge handelt.
public class Man {

   int dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1 == man2);
   }
}
Konsolenausgabe:

false
Es ist logisch, dass das Ergebnis dasselbe war (schließlich haben wir nichts geändert), aber jetzt sind wir damit nicht zufrieden! Tatsächlich ist die DNA-Analyse im wirklichen Leben eine hundertprozentige Garantie dafür, dass wir es mit Zwillingen zu tun haben. Aber unser Programm und unser Betreiber ==sagen uns etwas anderes. Wie können wir dieses Verhalten ändern und sicherstellen, dass das Programm bei Übereinstimmung der DNA-Tests das richtige Ergebnis liefert? Zu diesem Zweck wurde in Java eine spezielle Methode erstellt - equal() .

Equals()-Methode in Java

Wie die Methode, toString()die wir zuvor besprochen haben, gehört equal() zur Klasse, Objectder wichtigsten Klasse in Java, von der alle anderen Klassen abgeleitet sind. Equals() selbst wird jedoch das Verhalten unseres Programms in keiner Weise ändern:
public class Man {

   String dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = "111122223333";

       Man man2 = new Man();
       man2.dnaCode = "111122223333";

       System.out.println(man1.equals(man2));
   }
}
Konsolenausgabe:

false
Genau das gleiche Ergebnis. Warum wird diese Methode dann benötigt? :/ Es ist einfach. Tatsache ist, dass wir diese Methode jetzt so verwendet haben, wie sie in der Klasse selbst implementiert ist Object. Und wenn wir in den Klassencode gehen Objectund uns ansehen, wie diese Methode darin implementiert ist und was sie tut, werden wir sehen:
public boolean equals(Object obj) {
   return (this == obj);
}
Aus diesem Grund hat sich das Verhalten unseres Programms nicht geändert! In der Methode equal() der Klasse Objectbefindet sich derselbe Referenzvergleich, ==. Der Trick dieser Methode besteht jedoch darin, dass wir sie überschreiben können. Überschreiben bedeutet, dass Sie Ihre eigene equal()-Methode in unserer Klasse schreiben Manund dafür sorgen, dass sie sich so verhält, wie wir es wollen! Nun sind wir nicht davon überzeugt, dass die Prüfung man1.equals(man2)im Wesentlichen dasselbe bewirkt wie man1 == man2. Folgendes werden wir in dieser Situation tun:
public class Man {

   int dnaCode;

   public boolean equals(Man man) {
       return this.dnaCode ==  man.dnaCode;
   }

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1.equals(man2));

   }
}
Konsolenausgabe:

true
Ein völlig anderes Ergebnis! Indem wir anstelle der Standardmethode unsere eigene equal()-Methode geschrieben haben, haben wir das richtige Verhalten erreicht: Wenn nun zwei Personen den gleichen DNA-Code haben, sagt uns das Programm: „Die DNA-Analyse hat gezeigt, dass sie Zwillinge sind“ und gibt true zurück! Durch Überschreiben der Methode equal() in Ihren Klassen können Sie ganz einfach die erforderliche Objektvergleichslogik erstellen. Wir haben den Vergleich von Objekten nur allgemein angesprochen. Wir werden noch einen separaten großen Vortrag zu diesem Thema veranstalten (bei Interesse können Sie ihn jetzt schnell lesen).

String-Vergleich in Java – String-Vergleich

Warum behandeln wir Stringvergleiche getrennt von allem anderen? Tatsächlich sind Zeilen in der Programmierung eine ganz andere Geschichte. Erstens: Wenn man alle von der Menschheit geschriebenen Java-Programme betrachtet, bestehen etwa 25 % der darin enthaltenen Objekte aus ihnen. Daher ist dieses Thema sehr wichtig. Zweitens unterscheidet sich der Vergleich von Zeichenfolgen erheblich von dem Vergleich anderer Objekte. Schauen wir uns ein einfaches Beispiel an:
public class Main {

   public static void main(String[] args) {

       String s1 = „JavaRush ist die beste Seite, um Java zu lernen!“;
       String s2 = new String(„JavaRush ist die beste Seite, um Java zu lernen!“);
       System.out.println(s1 == s2);
   }
}
Konsolenausgabe:

false
Aber warum falsch? Die Zeilen sind Wort für Wort exakt gleich :/ Sie können davon ausgehen: Das liegt daran, dass der Operator == Referenzen vergleicht! Schließlich haben s1sie s2unterschiedliche Adressen im Speicher. Wenn Ihnen dieser Gedanke gekommen ist, wiederholen wir unser Beispiel:
public class Main {

   public static void main(String[] args) {

       String s1 = „JavaRush ist die beste Seite, um Java zu lernen!“;
       String s2 = „JavaRush ist die beste Seite, um Java zu lernen!“;
       System.out.println(s1 == s2);
   }
}
Jetzt haben wir auch zwei Links, aber das Ergebnis hat sich ins Gegenteil geändert: Konsolenausgabe:

true
Völlig verwirrt? :) Lass es uns herausfinden. Der Operator ==vergleicht tatsächlich Adressen im Speicher. Diese Regel funktioniert immer und es besteht kein Grund, daran zu zweifeln. Das heißt, wenn s1 == s2es „true“ zurückgibt, haben diese beiden Zeichenfolgen dieselbe Adresse im Speicher. Und das ist es tatsächlich! Es ist an der Zeit, sich mit einem speziellen Speicherbereich zum Speichern von Strings vertraut zu machen – dem String-Pool ( String pool). Gleichheits- und Zeichenfolgenvergleich - 3Der String-Pool ist ein Bereich zum Speichern aller String-Werte, die Sie in Ihrem Programm erstellen. Wozu wurde es geschaffen? Wie bereits erwähnt, nehmen Strings einen großen Teil aller Objekte ein. In jedem großen Programm werden viele Zeilen erstellt. Um Speicherplatz zu sparen, ist Folgendes erforderlich String Pool: Dort wird eine Zeile mit dem benötigten Text platziert, und neu erstellte Links verweisen in Zukunft auf denselben Speicherbereich. Es ist nicht erforderlich, jedes Mal zusätzlichen Speicher zuzuweisen. Jedes Mal, wenn Sie schreiben String = “........”, prüft das Programm, ob sich im String-Pool eine Zeile mit einem solchen Text befindet. Wenn dies der Fall ist, wird kein neues erstellt. Und der neue Link verweist auf dieselbe Adresse im String-Pool, wo dieser String gespeichert ist. Deshalb haben wir es in das Programm geschrieben
String s1 = „JavaRush ist die beste Seite, um Java zu lernen!“;
String s2 = „JavaRush ist die beste Seite, um Java zu lernen!“;
Der Link s2zeigt genau auf die gleiche Stelle wie s1. Der erste Befehl erstellte eine neue Zeile im String-Pool mit dem von uns benötigten Text, und als es zum zweiten kam, verwies er einfach auf denselben Speicherbereich wie s1. Sie können mindestens 500 weitere Zeilen mit demselben Text erstellen, das Ergebnis ändert sich nicht. Stoppen. Aber warum hat dieses Beispiel bei uns nicht früher funktioniert?
public class Main {

   public static void main(String[] args) {

       String s1 = „JavaRush ist die beste Seite, um Java zu lernen!“;
       String s2 = new String(„JavaRush ist die beste Seite, um Java zu lernen!“);
       System.out.println(s1 == s2);
   }
}
Ich denke, intuitiv erraten Sie bereits, was der Grund ist :) Versuchen Sie es zu erraten, bevor Sie weiterlesen. Sie können sehen, dass diese beiden Zeilen unterschiedlich erstellt wurden. Eines davon mit Hilfe des Operators new, das zweite ohne. Genau das ist der Grund. Der neue Operator weist beim Erstellen eines Objekts zwangsweise einen neuen Bereich im Speicher zu . Und die mit new, erstellte Zeile endet nicht in String Pool: Sie wird zu einem separaten Objekt, auch wenn ihr Text genau mit dem derselben Zeile aus 'a übereinstimmt String Pool. Das heißt, wenn wir den folgenden Code schreiben:
public class Main {

   public static void main(String[] args) {

       String s1 = „JavaRush ist die beste Seite, um Java zu lernen!“;
       String s2 = „JavaRush ist die beste Seite, um Java zu lernen!“;
       String s3 = new String(„JavaRush ist die beste Seite, um Java zu lernen!“);
   }
}
Im Speicher sieht es so aus: Gleichheits- und Zeichenfolgenvergleich - 4Und jedes Mal, wenn ein neues Objekt erstellt wird, newwird ein neuer Bereich im Speicher zugewiesen, auch wenn der Text in den neuen Zeilen derselbe ist! Wir scheinen den Operator geklärt zu haben ==, aber was ist mit unserem neuen Freund – der Methode equal()?
public class Main {

   public static void main(String[] args) {

       String s1 = „JavaRush ist die beste Seite, um Java zu lernen!“;
       String s2 = new String(„JavaRush ist die beste Seite, um Java zu lernen!“);
       System.out.println(s1.equals(s2));
   }
}
Konsolenausgabe:

true
Interessant. Wir wissen genau was s1und s2weisen auf verschiedene Bereiche im Gedächtnis hin. Dennoch besagt die Methode equal(), dass sie gleich sind. Warum? Denken Sie daran, dass wir oben gesagt haben, dass die Methode equal() in Ihrer Klasse überschrieben werden kann, sodass sie Objekte auf die von Ihnen benötigte Weise vergleicht? Das haben sie mit der Klasse gemacht String. Es verfügt über eine überschriebene equal()-Methode. Und es vergleicht nicht Links, sondern die Abfolge von Zeichen in Strings. Und wenn der Text in den Strings derselbe ist, spielt es keine Rolle, wie sie erstellt wurden und wo sie gespeichert sind: im String-Pool oder in einem separaten Speicherbereich. Das Ergebnis des Vergleichs wird wahr sein. Übrigens ermöglicht Ihnen Java den korrekten Vergleich von Zeichenfolgen ohne Berücksichtigung der Groß- und Kleinschreibung. Wenn Sie im Normalfall eine der Zeilen beispielsweise in Großbuchstaben schreiben, ist das Ergebnis des Vergleichs falsch:
public class Main {

   public static void main(String[] args) {

       String s1 = „JavaRush ist die beste Seite, um Java zu lernen!“;
       String s2 = new String("JAVARUSH - ЛУЧШИЙ САЙТ ДЛЯ ИЗУЧЕНИЯ JAVA!");
       System.out.println(s1.equals(s2));
   }
}
Konsolenausgabe:

false
Für diesen Fall verfügt die Klasse Stringüber eine Methode equalsIgnoreCase(). Wenn es bei Ihrem Vergleich vor allem auf die Reihenfolge bestimmter Zeichen und nicht auf deren Groß-/Kleinschreibung ankommt, können Sie diese verwenden. Dies ist beispielsweise beim Vergleich zweier E-Mail-Adressen nützlich:
public class Main {

   public static void main(String[] args) {

       String address1 = „Moskau, Akademiker-Korolev-Straße, 12“;
       String address2 = new String("Г. МОСКВА, УЛ. АКАДЕМИКА КОРОЛЕВА, ДОМ 12");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
In diesem Fall ist es offensichtlich, dass es sich um dieselbe Adresse handelt, sodass die Verwendung dieser Methode equalsIgnoreCase()die richtige Entscheidung ist.

String.intern()-Methode

Die Klasse Stringhat eine weitere knifflige Methode – intern(); Die Methode intern()funktioniert direkt mit String Pool'om. intern()Wenn Sie eine Methode für eine Zeichenfolge aufrufen , geschieht Folgendes:
  • Sucht nach einer Zeichenfolge mit diesem Text im Zeichenfolgenpool
  • Wenn dies der Fall ist, wird ein Link dazu im Pool zurückgegeben
  • Wenn nicht, wird eine Zeile mit diesem Text in den String-Pool eingefügt und ein Link darauf zurückgegeben.
Indem wir die Methode intern()auf die String-Referenz anwenden, die über new erstellt wurde, können wir sie mit der String-Referenz von String Pool'a über vergleichen ==.
public class Main {

   public static void main(String[] args) {

       String s1 = „JavaRush ist die beste Seite, um Java zu lernen!“;
       String s2 = new String(„JavaRush ist die beste Seite, um Java zu lernen!“);
       System.out.println(s1 == s2.intern());
   }
}
Konsolenausgabe:

true
Als wir sie zuvor ohne verglichen haben intern(), war das Ergebnis falsch. Nun prüfte die Methode , ob eine Zeile mit dem Text „JavaRush – die beste Seite zum Erlernen von Java!“intern() vorhanden war. im String-Pool. Natürlich ist es da: Wir haben es geschaffen, als wir geschrieben haben
String s1 = „JavaRush ist die beste Seite, um Java zu lernen!“;
Es wurde überprüft, ob die Referenz s1und die von der Methode zurückgegebene Referenz s2.intern()auf denselben Bereich im Speicher verweisen, und das ist natürlich auch der Fall :) Um es zusammenzufassen: Denken Sie an die Hauptregel und verwenden Sie sie: Um Zeichenfolgen zu vergleichen, verwenden Sie IMMER die Funktion equal() Methode! Wenn Sie Zeichenfolgen vergleichen, meinen Sie fast immer den Vergleich ihres Textes, nicht der Links, Speicherbereiche usw. Die Methode equal() macht genau das, was Sie brauchen. Hier finden Sie einige Links zum selbstständigen Lernen:
Kommentare
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION