In Bezug auf den Vergleich der Zeichenfolgentypäquivalenz in Java

Überblick

In der Programmiersprache "Java" wird "==" als Vergleichsoperator unterstützt, der die Äquivalenz darstellt. Beim Vergleich werden jedoch ** Referenztypen ** verwendet, die keine ** primitiven Typen ** sind, wie z. B. Zeichenfolgentypen Es wird ein unerwartetes Verarbeitungsergebnis sein. Unter dem Strich sollten Sie den Gleichheitsoperator "==" nicht verwenden, wenn Sie vergleichen, ob die Werte der ** Referenztypen gleich sind. ** ** **

In diesem Artikel werde ich darüber schreiben, warum Sie bei Vergleichen vom Typ String keine Gleichheitsoperatoren verwenden sollten und was passiert, wenn Sie dies tun. Diesmal konzentriert sich der Artikel jedoch nur auf den String-Typ, aber dies ist auch die Geschichte des Referenztyps im Allgemeinen.

Grundwissen

Primitiver Typ (Basisdatentyp)

Primitive Typen sind Typen, die die Daten selbst darstellen und kein Verhalten zum Bearbeiten der Daten aufweisen. Sie können einem primitiven Typ keine Null zuweisen.

Zum Beispiel gibt es die folgenden Typen.

Referenztyp

Im Gegensatz zu primitiven Typen erfordern Referenztypen die Verwendung des neuen Operators zum Erstellen und Zuweisen von Instanzen (Entitäten) zu Objekten, von denen jedes typspezifisches Verhalten aufweist. Sie können dem Referenztyp null zuweisen.

Zum Beispiel gibt es die folgenden Typen. Darüber hinaus kann der Hersteller die für die Bearbeitung des Antrags erforderlichen Typen und Prozesse definieren, die nicht die folgenden sind.

Übrigens, wenn Sie eine Sprache gelernt haben, die Zeiger verwendet, kennen Sie sie wahrscheinlich bereits. Für diejenigen, die in erster Linie "** Referenz **" sagen, wird dies empfohlen, da dies im folgenden Artikel ausführlich beschrieben wird. https://qiita.com/hys-rabbit/items/2e94c8722dc8f950e77c

Hauptthema

Was passiert, wenn Sie String-Typen mit Gleichheitsoperatoren vergleichen?

Betrachten Sie zunächst das Ausgabeergebnis anhand der folgenden Verarbeitung.

TestEquals.java


public final class TestEquals {
	public static void main(String[] args) {
		final String sequence1 = "test";
		final String newSequence = new String("test");

		System.out.println("Vergleich mit Gleichheitsoperator 1:");
		System.out.println(sequence1 == newSequence);
	}
}

Was ist nun das Ergebnis des Vergleichs derselben Zeichenfolge "test" mit dem Gleichheitsoperator? Auf den ersten Blick werden dieselben Zeichenketten verglichen, sodass das Vergleichsergebnis wahrscheinlich wahr ist. ** Im obigen Fall ist das Vergleichsergebnis jedoch immer falsch. ** ** **

Warum bekommen Sie dieses Ergebnis? Dies liegt daran, dass der Vergleich mit dem Gleichheitsoperator "==" ** bestimmt, ob die Daten an derselben Adresse im Speicher gespeichert sind **.

Es ist eine technische Geschichte, daher werde ich hier nicht auf Details eingehen, aber es ist wichtig zu fragen, was Erinnerung ist. In diesem Artikel werde ich jedoch nur einige empfohlene Artikel vorstellen. Wenn Sie es sich beim Lernen leisten können, sollten Sie einen Blick darauf werfen.

** Java Heap Memory Management Mechanismus ** https://www.atmarkit.co.jp/ait/articles/0504/02/news005.html

** Speicher aus dem Programm ** https://qiita.com/shinpeinkt/items/55c0d30754482e8235b9

Mit anderen Worten, im obigen Fall werden die Variable "sequence1" und die Variable "newSequence" in verschiedenen Bereichen im Speicher gespeichert. Wenn Sie also mit dem Gleichheitsoperator vergleichen, wird false zurückgegeben.

Ergänzung

Grundsätzlich ist das obige Verständnis für den Gleichheitsoperator ausreichend, In einigen Fällen überprüfen Sie diese bitte ebenfalls.

TestEquals.java


public final class TestEquals {
	public static void main(String[] args) {
		final String sequence1 = "test";
		final String sequence2 = "test";

		System.out.println("Vergleich mit Gleichheitsoperator 2:");
		System.out.println(sequence1 == sequence2);
	}
}

Der Unterschied zum ersten Beispiel besteht darin, dass die Variable "newSequence" mit dem neuen Operator initialisiert wurde, die Zeichenfolge "test" jedoch einfach der Variablen "sequence2" zugewiesen wird. Was ist das Verarbeitungsergebnis in den oben genannten Fällen? Ist es falsch ** Nein, im obigen Fall wird dies als wahr beurteilt. ** ** **

Dies liegt an einer Java-Funktion, die ich kurz erläutern werde. Wenn Sie initialisieren, indem Sie einer Variablen die Zeichenfolge "test" zuweisen, und dann initialisieren, indem Sie die Zeichenfolge "test" einer anderen Variablen auf dieselbe Weise zuweisen, wird sie im selben Bereich im Speicher verwaltet. Java verfügt über eine integrierte Funktionalität, mit der Sie Anpassungen vornehmen können, als ob Sie dies tun würden. Daher ist im obigen Fall das Verarbeitungsergebnis wahr.

Vergleich mit der Methode gleich

Lassen Sie uns nun die in der führenden String-Klasse definierte Methode equals berühren. Verwenden Sie zur Erinnerung die Methode equals wie folgt:

TestEquals.java


public final class TestEquals {
	public static void main(String[] args) {
		final String sequence1 = "test";
		final String sequence2 = "test";
		
		System.out.println("Vergleich mit gleich Methode 1:");
		System.out.println(sequence1.equals(sequence2));
		
		final String newSequence = new String("test");
		
		System.out.println("Vergleich mit gleich Methode 2:");
		System.out.println(sequence1.equals(newSequence));
	}
}

Beim Vergleich mit der Methode equals wird true in beiden Mustern im obigen Beispiel zurückgegeben. Nun, wer ist die in der String-Klasse definierte Methode equals und welche Art der Verarbeitung ist definiert?

Funktionsweise der in der String-Klasse definierten Methode equals

Der folgende Code ist die Verarbeitung der in der String-Klasse definierten Methode equals.

String.java


    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = length();
            if (n == anotherString.length()) {
                int i = 0;
                while (n-- != 0) {
                    if (charAt(i) != anotherString.charAt(i))
                            return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }

Auf den ersten Blick mag es schwierig erscheinen, aber wenn Sie sich ansehen, wie es beim Zerlegen funktioniert, ist es eine sehr einfache Implementierung.

Zunächst wird der Vergleich mit dem Gleichheitsoperator durchgeführt, und true wird zurückgegeben, wenn die Referenzen gleich sind. Dies ist der Fall beim Initialisieren, indem einer Variablen direkt eine Zeichenfolge zugewiesen wird, wie im vorherigen Beispiel erwähnt.

Dann ist es der Beurteilungsprozess, wenn sich das Referenzziel vom nächsten Block unterscheidet. Zunächst wird bestimmt, ob die als Argument übergebene Instanz des Objekts vom Typ String ist, und wenn sie nicht vom Typ String ist, wird false zurückgegeben, da es sich in erster Linie um völlig andere Daten handelt. Wenn das Argumentobjekt vom Typ String ist, wird es von Anfang an zeichenweise überprüft, um festzustellen, ob es der zu vergleichenden Zeichenfolge entspricht. Schließlich muss die Implementierung true zurückgeben, wenn alle Zeichen dem Vergleichsziel entsprechen.

Aus dem Obigen können Sie ersehen, dass die in der String-Klasse implementierte Methode equals alle Schwächen des Vergleichs mit dem zuvor gesehenen Gleichheitsoperator abdeckt.

Achtung (gängige Praxis in Java)

Wenn Sie so weit lesen möchten, haben Sie möglicherweise bemerkt, dass immer eine NullPointerException auftritt, wenn die String-Klasse, die die equals-Methode verwendet, null wird. Daher müssen Sie als Java-Benutzer die folgenden Regeln befolgen.

Das heißt, der Implementierer muss sicherstellen, dass die String-Klasse, die die equals-Methode verwendet, nicht null ist. Abhängig von der Implementierung kann es natürlich Situationen geben, in denen es nicht konstant gemacht werden kann. Wenn Sie jedoch weiterhin die Verarbeitung des Programms garantieren, sollten Sie es so gestalten, dass null nicht eingegeben wird.

Schließlich

Ich habe das schon lange geschrieben, aber wie war es? Ich weiß, dass einige Erklärungen fehlen, aber ich hoffe, dass dieser Artikel denjenigen helfen wird, die mit dem Programmieren mit Java begonnen haben.

Referenzmaterial

https://morizyun.github.io/java/type-primitive-reference.html - Java-Primitiv- und Referenztypen https://qiita.com/hys-rabbit/items/2e94c8722dc8f950e77c - Java-Referenz zum Verständnis in der Abbildung https://www.atmarkit.co.jp/ait/articles/0504/02/news005.html - Java-Heap-Speicherverwaltungsmechanismus https://qiita.com/shinpeinkt/items/55c0d30754482e8235b9 - Speicher aus Sicht des Programms

Recommended Posts

In Bezug auf den Vergleich der Zeichenfolgentypäquivalenz in Java
[Java] Korrekter Vergleich des String-Typs
[Java] Vergleich von Zeichenketten und && und ||
Typbestimmung in Java
Die Geschichte des einfachen String-Vergleichs in Java
Probieren Sie den Funktionstyp in Java aus! ①
[Java] Vergleich der Geschwindigkeit der Typkonvertierung
Ich habe versucht, in Java von einer Zeichenfolge in einen LocalDate-Typ zu konvertieren
[Java] Geschwindigkeitsvergleich der Zeichenfolgenkombination
Java-Zeichenfolge
[Leicht verständliche Erklärung! ] Konvertierung des Referenztyptyps in Java
[Java] Spickzettel für Datentyp / Zeichenkettenklasse
Hinweise zu Operatoren, die Java ~ String type ~ verwenden
[Java] Konvertiert Null vom Objekttyp in String-Typ
Alle gleichen Hash-Code-Zeichenfolgen in Java
Teilen Sie eine Zeichenfolge in Java mit ". (Dot)"
Java 8 LocalDateTime-Typkonvertierung (String, java.util.Date)
Typkonvertierung vom Java Big Decimal-Typ zum String-Typ
[Java] Zeigt die Bitfolge an, die in der Bytetypvariablen auf der Konsole gespeichert ist
[Java] Äquivalenzvergleich, bei dem Anfänger beim Vergleich von Zeichenfolgen fehlschlagen. Möglicherweise sind Sie sich des Fehlers nicht einmal bewusst! ??
Java-Typkonvertierung
In Bezug auf transiente Modifikatoren und Serialisierung in Java
[Java] Unterschied zwischen gleich und == in einer Zeichenfolge, die ein Referenztyp ist
Lesen Sie eine Zeichenfolge in einer PDF-Datei mit Java
Partisierung in Java
[Java] Auffüllen von Zeichenfolgen
MyBatis-Zeichenfolgenvergleich
Der in Java 10 eingeführte Schnittpunkttyp ist erstaunlich (?)
[Java] Aufzählungstyp
Java Optionaler Typ
Code zum Escapezeichen von JSON-Zeichenfolgen in Java
Änderungen in Java 11
Informationen zu in Java verwendeten Variablen (lokaler Variablentyp)
Janken in Java
Java-Doppeltyp
[Java] Kartenvergleich
Java-String-Verarbeitung
Java Framework Vergleich
Organisiertes Memo im Kopf (Java - Datentyp)
Java-Typkonvertierung (String, int, Datum, Kalender usw.)
Umfangsrate in Java
Geteilter String (Java)
Warum der Klassenvergleich vom Typ Java String (==) nicht verwendet werden kann
Wie schreibe ich Java String # getBytes in Kotlin?
FizzBuzz in Java
Beispielcode zum Konvertieren von List in List <String> in Java Stream
[String type vs String Builder] Unterschied in der Verarbeitungsgeschwindigkeit in der String-Kombination
[Java] Vergleich der Ausführungsgeschwindigkeit des String-Joins (+ Operator vs StringBuilder)
[Java] Hinweise zur Typinferenz in Java 10
Äquivalenter Vergleich von Java-Wrapper-Klasse und primitivem Typ
Lesen Sie JSON in Java
Interpreter-Implementierung durch Java
Machen Sie einen Blackjack mit Java
Janken App in Java
Einschränkungsprogrammierung in Java
Setzen Sie Java8 in Centos7
NVL-artiger Typ in Java
Verbinden Sie Arrays in Java