Dieser Artikel ist der dritte Tag des Shizudai Information LT-Turnier-Adventskalenders 2019.
Es ist eine einfache Geschichte. Es ist leicht zu lesen, ob Java vorerst normalisiert werden kann. Wenn Sie Zeichenfolgen verglichen haben, können Sie diese vorerst lesen.
Vergleichen Sie beim Vergleichen von Zeichenfolgen in Java nicht mit "==". Verwenden Sie die Methode String # equals.
public class Test {
public static void main(String[] args) {
String a = "HelloWorld";
String b = "Hello";
b += "World";
System.out.println(a == b); // false
System.out.println(a.equals(b)); // true
}
}
public class Test {
public static void main(String[] args) {
String a = "HelloWorld";
String b = "HelloWorld";
System.out.println(a == b); // true
System.out.println(a.equals(b)); // true
}
}
Warum?
JVM "==" Wird oft als Vergleich der Adresspositionen bezeichnet, aber schauen wir uns das genauer an.
In Java wird "==" zur Kompilierungszeit häufig in eine der JVM-Anweisungen konvertiert, z. B. "if_acmpne" oder "if_acmpeq".
In einer JVM werden beim Kompilieren einer Java-Datei viele Klassendateien generiert, oder? Die Java Virtual Machine (JVM) interpretiert die Klassendatei und führt sie aus. Klassendateien haben ein Format, das viele Menschen nicht lesen können (und selten lesen), aber auf einer JVM (Computer) leichter zu lesen sind. Da die JVM ein komplexes Programm durch Kombinieren mehrerer einfacher Anweisungen realisiert, wird in Java häufig nur eine Anweisung in mehrere Anweisungen konvertiert.
Welche Art von Anweisung dann "if_acmpne" oder "if_acmpeq" ist, ist eine Anweisung, die zwei aus dem Operandenstapel herausnimmt, prüft, ob sie übereinstimmen, und zur Zeile des angegebenen Programms springt.
Operandenstapel ……? Die JVM wird als Stapelmaschine bezeichnet und verwendet keine Register, sondern ein Gerät, das als "Stapel" bezeichnet wird, um verschiedene Operationen auszuführen.
Der Operandenstapel ist wie ein Arbeitsbereich. Es wird häufig verwendet, da es für Operationen mit vier Regeln genau richtig ist. (Umgekehrte polnische Notation usw.)
Zum Beispiel können 5 + 12 durch den folgenden Mechanismus berechnet werden.
Der Operandenstapel in Java enthält jedoch nur ein Element mit bis zu 32 Bit.
Wenn ein Zeichen durch Java dargestellt wird, wird ein Element (= 32 Bit) dieses Operandenstapels verbraucht. Die Zeichenfolge hat eine variable Größe. Manchmal behandeln wir ein Zeichen und manchmal Hunderte von Zeichen wie in diesem Artikel. Mit anderen Worten, ein Element des Operandenstapels (= 32 Bit) kann überhaupt nicht alle Zeichen verarbeiten.
Daher wird die Zeichenfolge in einem anderen Speicher gespeichert, und die Adresse dieses Speichers (Adresse auf dem Computer) wird im Operandenstapel gespeichert. Infolgedessen reicht ein Element des Operandenstapels (= 32 Bit) aus.
Wie bereits erwähnt, werden "if_acmpne" und "if_acmpeq" aus dem Operandenstapel übernommen. Wenn sie für "if_acmpeq" gleich und für "if_acmpne" nicht gleich sind, springen sie zu einer anderen angegebenen Zeile. (Springen ist wie ein gewöhnlicher GOTO-Befehl)
Mit anderen Worten, im Fall von "if_acmpeq" wird ein Sprungbefehl erzeugt, wenn die Nummern der Adressen auf dem Operandenstapel gleich sind. Im zweiten Quellcode auf dieser Seite ("Moment mal") wurde "Hello World" unter derselben Adresse gespeichert, sodass es als "true" angezeigt wird.
Das ist es.
Also, was denkst du wird das sein? Bitte verzeihen Sie, dass die Benennung angemessen ist
public class Test {
public static void main(String[] args) {
String a = "HelloWorld";
method1(a);
}
public static void method1(String c) {
String k = "HelloWorld";
System.out.println(k == c);
}
}
Die Antwort ist "wahr".
Java-Klassendateien haben einen konstanten Bereich. In diesem konstanten Bereich werden beim Kompilieren hauptsächlich Zeichenfolgen usw. gespeichert. Dinge wie magische Zahlen und magische Zeichenfolgen (?) Werden in diesem konstanten Bereich gespeichert und in den Speicher geladen und verwendet, wenn die JVM die Klassendatei liest. Zum Beispiel
System.out.println("Hello Ja! Ja!");
Zum Beispiel "Hallo Ja! Ja!" Wird im konstanten Bereich gespeichert und die Zeichenfolge wird von dort gelesen.
Außerdem ist der Java-Compiler so intelligent, dass selbst wenn dieselbe Zeichenfolge zweimal angezeigt wird, sie aus demselben konstanten Bereich gelesen wird, wenn sie zuvor mehrmals verwendet wurde. Mit anderen Worten, im vorherigen Code waren die Adressen, auch wenn die Methoden unterschiedlich waren, dieselben, da sie sich auf die Zeichenfolge "Hello World" im konstanten Bereich derselben Klasse bezogen.
Wenn Sie sich den konstanten Bereich der Klassendatei ansehen, wird "Hallo Welt" ordnungsgemäß gespeichert.
Nebenbei habe ich im ersten Quellcode auf dieser Seite die Zeichenfolgen absichtlich in zwei Teile geschrieben, "Hallo" und "Welt", um den Speicherbereich zu trennen. Der Java-Compiler scheint nicht so viel zu tun. C-Compiler tun dies häufig.
Es wird von der String-Klasse überschrieben und ist ein Code, der den Inhalt fest vergleicht Der Bildcode sieht wie folgt aus. Nicht die ursprüngliche Mutter.
@Override
public boolean equals(String str) {
if(this.length() != str.length()) {
return false;
}
for(int i = 0; i < str.length(); i++) {
if(this.charAt(i) != str.charAt(i)) { //Sie können jedes beliebige n-te Zeichen mit charAt abrufen
return false;
}
}
return true;
}
Es ist linear und vergleicht die Zeichen einzeln von vorne. Es gibt kein Problem, da ein Zeichen in 32 Bit passt.
Verwenden Sie beim Vergleichen von Zeichenfolgen die Methode equals. Wenn es mit "==" wahr wird, wird es an derselben Stelle gespeichert. Hmmm.
Der Adventskalender von morgen ist auch gut! .. Adventskalender des Shizudai Information LT-Turniers 2019
Recommended Posts