Ich weiß, dass dies eine alte Frage ist, aber ich sehe das folgendermaßen (ich finde es sehr nützlich):
Technische Erläuterungen
In Java sind alle Variablen entweder primitive Typen o Referenzen .
(Wenn Sie wissen wollen, was eine Referenz ist: "Objektvariablen" sind einfach Zeigern auf Objekte. Also mit Object something = ...
etwas ist in Wirklichkeit eine Adresse im Speicher (eine Zahl)).
==
vergleicht die genauen Werte. Es wird also verglichen, ob die primitiven Werte gleich sind, oder ob die Referenzen (Adressen) gleich sind. Deshalb ist ==
funktioniert oft nicht bei Strings; Strings sind Objekte, und die ==
auf zwei String-Variablen vergleicht nur, ob die Adresse im Speicher die gleiche ist, wie andere bereits erwähnt haben. .equals()
ruft die Vergleichsmethode von Objekten auf, die die tatsächlichen Objekte vergleicht, auf die die Verweise zeigen. Im Fall von Strings wird jedes Zeichen verglichen, um festzustellen, ob sie gleich sind.
Der interessante Teil :
Warum also ==
manchmal true für Strings zurückgeben? Beachten Sie, dass Strings unveränderlich sind. In Ihrem Code, wenn Sie
String foo = "hi";
String bar = "hi";
Da Zeichenketten unveränderlich sind (wenn Sie die .trim()
oder etwas anderes, wird eine neue Zeichenkette erzeugt, ohne das ursprüngliche Objekt, auf das im Speicher verwiesen wird, zu verändern), brauchen Sie nicht wirklich zwei verschiedene String("hi")
Objekte. Wenn der Compiler schlau ist, wird der Bytecode so gelesen, dass er nur ein String("hi")
Objekt. Wenn Sie also
if (foo == bar) ...
gleich danach, zeigen sie auf dasselbe Objekt und geben true zurück. Aber das ist selten Ihre Absicht. Stattdessen fragen Sie nach Benutzereingaben, die neue Zeichenfolgen an verschiedenen Stellen des Speichers erstellen, usw. usw.
Hinweis : Wenn Sie etwas tun wie baz = new String(bar)
kann der Compiler immer noch herausfinden, dass es sich um dasselbe handelt. Aber der wichtigste Punkt ist, wenn der Compiler sieht literalen Zeichenfolgen, kann es leicht optimieren gleichen Zeichenfolgen.
Ich weiß nicht, wie es zur Laufzeit funktioniert, aber ich gehe davon aus, dass die JVM keine Liste von "Live-Strings" führt und prüft, ob eine gleiche Zeichenkette existiert. (z.B. wenn eine Eingabezeile zweimal gelesen wird und der Benutzer zweimal dieselbe Eingabe eingibt, wird nicht geprüft, ob die zweite Eingabezeichenkette dieselbe ist wie die erste, und sie werden in denselben Speicher geleitet). Es würde ein bisschen Heap-Speicher sparen, aber der Overhead ist so vernachlässigbar, dass es sich nicht lohnt. Nochmals, der Punkt ist, dass es für den Compiler einfach ist, literale Zeichenketten zu optimieren.
Da haben Sie es... eine düstere Erklärung für ==
vs. .equals()
und warum es zufällig erscheint.