Heim > Java > javaLernprogramm > Was vergleicht String mit der Methode equal und ==?

Was vergleicht String mit der Methode equal und ==?

高洛峰
Freigeben: 2016-12-16 09:38:27
Original
1348 Leute haben es durchsucht

Der Unterschied zwischen der Methode equal und ==

Zunächst einmal weiß jeder, dass String sowohl als Objekt als auch als Basistyp verwendet werden kann. Hiermit ist gemeint, dass sich die Verwendung als Basistyp nur auf die Verwendungsmethode bezieht, z. B. String s = „Hallo“. Es wird auf die gleiche Weise wie der Basistyp int verwendet, z. B. int i = 1;, und Die Verwendung als Objekt bezieht sich auf das Erstellen eines neuen Objekts über das Schlüsselwort new, z. B. String s = new String("Hallo"). Aber seine interne Aktion erzeugt tatsächlich ein Objekt, worauf später noch eingegangen wird.

Zweitens müssen Sie die Vergleichsmethode von String-Objekten verstehen. Es gibt zwei Konzepte für den Vergleich zwischen Objekten in Java: Das eine besteht darin, „==“ für den Vergleich von zwei Variablen vom Typ „String“ zu verwenden Variablen: Wenn sie auf dasselbe String-Objekt verweisen (d. h. auf denselben Speicherheap verweisen), ist das Ergebnis des „==“-Vergleichs wahr. Die andere Möglichkeit besteht darin, die Methode equal() des Object-Objekts zum Vergleich zu verwenden. Das String-Objekt erbt von Object und überschreibt die Methode equal(). Wenn zwei String-Objekte mit der Methode equal() verglichen werden, wird der vom String-Objekt gekapselte String-Inhalt tatsächlich verglichen. Das heißt, wenn der von den beiden String-Objekten gekapselte String-Inhalt derselbe ist (einschließlich der gleichen Groß-/Kleinschreibung), Dann gibt die Methode equal() true zurück.

Jetzt beginnen wir mit einer detaillierten Analyse der Erstellung von String-Objekten:

1. /////////////////// /// //////////////////////////////////////////// ///////

String s1 = new String("Hello");

String s2 = new String("Hello");

System.out .println(s1 == s2 );

System.out.println(s1.equals(s2));

Das Druckergebnis des obigen Codesegments ist:

false

true

Ich glaube, dieses Ergebnis ist für jeden leicht zu verstehen. Die beiden String-Typvariablen s1 und s2 erstellen jeweils ein neues String-Objekt durch das neue Schlüsselwort Neuer Block für jedes erstellte Objekt, unabhängiger Speicherheap. Daher wird beim Vergleich, ob sie über „==“ auf dasselbe Objekt verweisen, false zurückgegeben. Beim Vergleich mit der Methode equal() wird true zurückgegeben, da die von den beiden Objekten gekapselten String-Inhalte genau gleich sind.

2. ///////////////////////////////////// / //////////////////////////////////////

String s1 = new String("Hallo");

String s2 = s1;

System.out.println(s1 == s2);

System.out.println(s1 . equal(s2));

Das gedruckte Ergebnis des obigen Codeausschnitts ist:

wahr

wahr

Dieses Ergebnis sollte besser verstanden werden, Die Variable s1 ist immer noch ein neues String-Objekt, das über das neue Schlüsselwort erstellt wird, aber hier erstellt s2 kein neues String-Objekt über das neue Schlüsselwort, sondern weist s1 direkt s2 zu, dh weist die Referenz von s1 s2 zu Das von s2 referenzierte Objekt ist tatsächlich das von s1 referenzierte Objekt. Beim Vergleich mit „==“ wird also „true“ zurückgegeben. Da sie sich alle auf dasselbe Objekt beziehen, wird beim Vergleich mit der Methode equal() auf jeden Fall true zurückgegeben. Die Methode equal() vergleicht hier tatsächlich dasselbe Objekt und muss mit sich selbst identisch sein.

3. ///////////////////////////////////// / ///////////////////////////////////

String s1 = „Hallo“ ;

String s2 = "Hallo";

System.out.println(s1 == s2);

System.out.println(s1.equals(s2) );

Das gedruckte Ergebnis des obigen Codeausschnitts ist:

wahr

wahr

Warum dieses Ergebnis? Also lasst es uns analysieren. Zunächst werden diese beiden String-Objekte als Basistyp verwendet und nicht über das neue Schlüsselwort erstellt. Daher weist die virtuelle Maschine keinen neuen Speicherheap für diese beiden String-Objekte zu, sondern für den String-Pufferpool finden.

Finden Sie zunächst für s1 heraus, ob sich im String-Pufferpool ein String-Objekt mit demselben Wert wie „Hello“ befindet. Zu diesem Zeitpunkt ist der String-Pufferpool leer und es gibt kein String-Objekt mit demselben Wert Wert, sodass sich die virtuelle Maschine im String-Pufferpool befindet. Um dieses String-Objekt zu erstellen, lautet die Aktion new String("Hello");. Weisen Sie dann s1 die Referenz dieses String-Objekts zu.

Suchen Sie dann nach s2, um zu sehen, ob sich im String-Pufferpool ein String-Objekt mit demselben Wert wie „Hello“ befindet Das Objekt wurde tatsächlich für das String-Objekt erstellt. Nachdem nun ein Objekt mit demselben Wert gefunden wird, erstellt die virtuelle Maschine hierfür kein neues String-Objekt mehr, sondern weist s2 direkt die Referenz des vorhandenen String-Objekts zu.

Da s1 und s2 auf dasselbe String-Objekt verweisen, das heißt, sie sind sich selbst gleich, geben die beiden oben genannten Vergleichsmethoden true zurück.

An diesem Punkt sollten Sie die Grundkonzepte von String-Objekten verstanden haben. Lassen Sie mich nun zusammenfassen:

String als Grundtyp verwenden:

1. Wenn String als Basistyp verwendet wird, betrachten wir dieses String-Objekt als Eigentum des String-Pufferpools.

2. Wenn String als Basistyp verwendet wird und zu diesem Zeitpunkt kein String-Objekt mit demselben angegebenen Wert im String-Pufferpool vorhanden ist, erstellt die virtuelle Maschine dafür ein neues String-Objekt und speichert es im String-Pufferpool.

3. Wenn String als Basistyp verwendet wird und zu diesem Zeitpunkt ein String-Objekt mit demselben angegebenen Wert im String-Pufferpool vorhanden ist, erstellt die virtuelle Maschine hierfür kein neues String-Objekt, sondern gibt direkt einen Verweis darauf zurück vorhandenes String-Objekt.

String als Objekt verwenden:

1. Wenn String als Objekt verwendet wird, erstellt die virtuelle Maschine ein neues String-Objekt dafür, weist also einen neuen Speicherheap für dieses Objekt zu. Es gehört nicht dem String-Pufferpool, ist also unabhängig.

Nachdem Sie das oben Gesagte verstanden haben, schauen Sie sich bitte den folgenden Codeausschnitt an:

4. / ////////////////////////////////////////////// ///// ///

String s1 = "Hello";

String s2 = new String("Hello");

System.out.println( s1 == s2) ;

System.out.println(s1.equals(s2));

Das Druckergebnis des obigen Codesegments ist:

false

wahr

Führen Sie eine Analyse basierend auf der obigen Zusammenfassung durch. Die erste Zeile verwendet String als Basistyp, sodass das von s1 referenzierte Objekt zum String-Pufferpool gehört. Und zu diesem Zeitpunkt gibt es im String-Pufferpool kein String-Objekt mit demselben Wert, daher erstellt die virtuelle Maschine dafür ein neues String-Objekt, nämlich new String("Hello");. Die zweite Zeile verwendet String als Objekt, sodass das von s2 referenzierte Objekt nicht zum String-Pufferpool gehört, dh unabhängig ist. Über das Schlüsselwort new erstellt die virtuelle Maschine zu diesem Zweck ein neues String-Objekt, das heißt, sie weist ihm einen neuen Speicherheap zu. Daher ist das Ergebnis des „==“-Vergleichs falsch, da s1 und s2 nicht auf dasselbe Objekt verweisen, sondern unabhängig voneinander existieren. Die Methode equal() gibt true zurück, da die von den beiden Objekten gekapselten String-Inhalte genau gleich sind.

Nun glaube ich, dass jeder vollständig verstanden hat, was das String-Objekt ist :) Aber damit ist es noch nicht vorbei, denn das String-Objekt hat tiefere Anwendungen.

Hier werde ich die Anwendung der intern()-Methode des String-Objekts analysieren:

Die intern()-Methode gibt die kanonische Darstellung eines String-Objekts zurück, also einen String mit dem Gleicher Inhaltsstring, aber aus einem String-Pufferpool mit eindeutigen Strings. Das hört sich etwas übertrieben an, aber sein Mechanismus ist tatsächlich wie folgt:

String s = new String("Hello");

s = s.intern();

Die funktionale Implementierung des obigen Codesegments kann einfach als folgendes Codesegment betrachtet werden:

String s = "Hello";

Du fragst dich bestimmt schon wieder? Dann können Sie sich zunächst den zweiten Codeausschnitt ansehen. Die Bedeutung des zweiten Codeausschnitts besteht darin, einen Verweis auf ein String-Objekt mit demselben Wert aus dem String-Pufferpool zu nehmen und ihn s zuzuweisen. Wenn im String-Pufferpool kein String-Objekt mit demselben Wert vorhanden ist, wird darin ein neues String-Objekt erstellt. Was bedeutet also der erste Code? Wir wissen, dass die virtuelle Maschine für Objekte, die mit dem Schlüsselwort new erstellt wurden, einen neuen Speicherheap zuweist. Wenn Sie auf einfache Weise ein Objekt mit demselben Inhalt erstellen, wird die virtuelle Maschine ihm auch viele neue Speicher-Heaps zuweisen, obwohl deren Inhalt genau gleich ist. Nehmen wir als Beispiel String-Objekte: Wenn kontinuierlich 10 String-Objekte mit demselben Inhalt (neuer String („Hallo“)) erstellt werden, weist die virtuelle Maschine ihnen 10 unabhängige Speicherheaps zu. Angenommen, der String-Inhalt des erstellten String-Objekts ist sehr groß. Wenn wir 10 identische String-Objekte erstellen, verschwenden wir sinnlos 9 MB Speicherplatz. Wir wissen, dass String eine endgültige Klasse ist und dass sie eine String-Konstante kapselt. Daher kann der interne (String-)Wert des String-Objekts nach seiner Erstellung nicht geändert werden, und daher kann das String-Objekt gemeinsam genutzt werden. Unter der gerade erwähnten Annahme müssen wir für die 10 String-Objekte, die wir mit demselben Inhalt erstellt haben, tatsächlich nur ein String-Objekt erstellen, das dann von anderen String-Variablen gemeinsam genutzt wird. Um diesen Mechanismus zu implementieren, besteht die einzige und einfache Möglichkeit darin, den String-Pufferpool zu verwenden, da im String-Pufferpool keine String-Objekte mit demselben Inhalt vorhanden sind. Die Methode intern() ist die Möglichkeit, diesen Mechanismus zu nutzen. Nach dem Aufruf der intern()-Methode für ein instanziiertes String-Objekt sucht die virtuelle Maschine nach einem String-Objekt mit demselben Wert wie der von diesem Stirng-Objekt gekapselte String-Inhalt im String-Pufferpool und weist dann den Verweis dem ursprünglichen String-Objekt zu . Variable vom Typ String. Wenn im String-Pufferpool kein String-Objekt mit demselben Wert wie der von diesem String-Objekt gekapselte String-Inhalt vorhanden ist, erstellt die virtuelle Maschine zu diesem Zweck ein neues String-Objekt und weist seinen Verweis der Variablen vom Typ String zu, die auf verweist ursprüngliches String-Objekt. Auf diese Weise wird der Zweck der gemeinsamen Nutzung desselben String-Objekts erreicht und das ursprüngliche String-Objekt, das mit dem neuen Schlüsselwort erstellt wurde, wird vom Garbage Collector verworfen und recycelt. Dies reduziert nicht nur die Speichernutzung und verbessert die Leistung, sondern erleichtert auch den Vergleich von String-Objekten, da dieselben String-Objekte gemeinsam genutzt werden. Um festzustellen, ob zwei String-Objekte gleich sind, müssen Sie zum Vergleichen nur „==“ verwenden Dies ist nicht nur bequemer zu verwenden, sondern verbessert auch die Leistung, da die Methode equal() des String-Objekts den String-Inhalt zerlegt und ihn dann einzeln verarbeitet Wenn der Zeichenfolgeninhalt sehr groß ist, verringert diese Vergleichsaktion die Leistung erheblich.

Trotzdem sind Sie vielleicht immer noch etwas vage bezüglich der konkreten Anwendung, deshalb möchte ich ein einfaches Beispiel geben, um das obige Konzept zu veranschaulichen:

Angenommen, es gibt eine Klasse, die eine Nachricht hat Protokollierungsfunktion Methode: Diese Methode zeichnet die vom Benutzer gesendeten Nachrichten auf (vorausgesetzt, der Nachrichteninhalt ist möglicherweise groß und die Wiederholungsrate hoch) und zeichnet die Nachrichten in der Reihenfolge ihres Empfangs in einer Liste auf. Ich denke, einige Freunde werden es so entwerfen:

import java.util.*;

public class Messages {

ArrayList messages = new ArrayList();

public void record(String msg) {

messages.add(msg);

}

public List getMessages() {

return Nachrichten;

}

}

Ist dieses Design gut? Angenommen, wir senden wiederholt dieselbe Nachricht an die Methode record () (die Nachricht stammt von verschiedenen Benutzern, sodass jede Nachricht als neuer String ("...") betrachtet werden kann) und der Nachrichteninhalt ist groß, dann ist dieser Entwurf so Dies ist eine große Verschwendung von Speicherplatz, da alle Datensätze in der Nachrichtenliste neu erstellte, unabhängige String-Objekte sind, obwohl ihr Inhalt derselbe ist. Wie können wir es also optimieren? Sehen Sie sich bitte das folgende optimierte Beispiel an:

import java.util.*;

public class Messages {

ArrayList messages = new ArrayList();

public void record(String msg) {

messages.add(msg.intern());

}

public List getMessages() {

return messages;

}

}

Wie Sie sehen können, ist die ursprüngliche record()-Methode die messages.add (msg); Das Codesegment in wurde zu messages.add(msg.intern());, das nur die intern()-Methode für den msg-Parameter aufruft. Dadurch wird ein Mechanismus zur gemeinsamen Nutzung doppelter Nachrichten erstellt, wodurch die Speicherkosten gesenkt werden Verbrauch, verbesserte Leistung.

Dieses Beispiel ist zwar etwas weit hergeholt, dient aber nur der Veranschaulichung des oben genannten Konzepts!

An diesem Punkt wurde der Nebel von String-Objekten beseitigt. Solange Sie diese Konzepte im Hinterkopf behalten, kann jede komplexe String-Anwendung in der Zukunft auf dieser Grundlage analysiert werden.




Weitere verwandte Artikel darüber, welche String-Methoden „equals“ bzw. „==“ zum Vergleichen verwenden. Folgen Sie der chinesischen PHP-Website!


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage