[JAVA] String- und Heap-Bereich und konstanter Pool
Java-Speicherbereich
Grob!
- Registrierung dt>
- Existiert in CPU und kann nicht gesteuert werden dd>
- Stapelbereich dt>
- Basistyp, Referenzwert wird gespeichert dd>
- Die Speicherverwaltung erfolgt durch Hin- und Herbewegen des Punkts dd>
- Heap-Bereich dt>
- Objekt erstellt von new dd>
- statischer Bereich dt>
- Wie das Wort schon sagt, statische Mitglieder dd>
- constant pool
- Daten, die zur Kompilierungszeit bestätigt wurden und in .class + other dd> vorhanden sind
- Nicht-RAM-Bereich dt>
- hdd usw. dd>
String- und Heap-Bereich und konstanter Pool
Hauptthema:
Ich möchte "Daten überprüfen, die zum Zeitpunkt der Kompilierung bestätigt wurden und in .class vorhanden sind".
Überprüfung vertrauter Inhalte
Im konstanten Pool generiert
String a1 = "aaa";
String a2 = "aaa";
System.out.println(a1 == a2); // true
- "aaa" wird im Contant-Pool-Bereich generiert, und der Referenzwert a1, der auf "aaa" zeigt, wird im Stack-Bereich generiert.
- Da sich im Bereich des Contant-Pools "aaa" befindet, wird im Stapelbereich ein Referenzwert a2 generiert, der auf "aaa" zeigt.
- Da sowohl a1 als auch a2 die Adresse "aaa" enthalten, wird dies wahr.
Im Heap-Bereich generiert
String a3 = new String("aaa");
String a4 = new String("aaa");
System.out.println(a3 == a4); // false
- "aaa" wird im Heap-Bereich erzeugt, und der Referenzwert a3, der auf "aaa" zeigt, wird im Stapelbereich erzeugt.
- "aaa" wird im Heap-Bereich erzeugt, und der Referenzwert a4, der auf "aaa" zeigt, wird im Stapelbereich erzeugt.
- a3 und a4 sind falsch, weil sie unterschiedliche "aaa" -Adressen enthalten.
Generiert in konstantem Pool, Heap-Bereich
String a5 = "aaa";
String a6 = new String("aaa");
System.out.println(a5 == a6); // false
- "aaa" wird im konstanten Poolbereich erzeugt, und der Referenzwert a5, der auf "aaa" zeigt, wird im Stapelbereich erzeugt.
- "aaa" wird im Heap-Bereich generiert, und der Referenzwert a6, der auf "aaa" zeigt, wird im Stapelbereich generiert.
- a5 und a6 sind falsch, weil sie unterschiedliche "aaa" -Adressen enthalten.
Überprüfung von etwas ungewöhnlichen Inhalten
Konstante + Konstante
String a1 = "ab";
String a2 = "a" + "b";
System.out.println(a1 == a2); // true
- "ab" wird im konstanten Poolbereich erzeugt, und der Referenzwert a1, der auf "ab" zeigt, wird im Stapelbereich erzeugt.
- "a" ist eine Konstante, "b" ist eine Konstante, also ist a2 = "ab" zur Kompilierungszeit.
Es wird ein Referenzwert a2 generiert, der auf "ab" zeigt, das in der konstanten Abfrage vorhanden ist.
- Da sowohl a1 als auch a2 die Adresse "ab" enthalten, wird dies wahr.
- Als ich es mit Dekompilierung betrachtete, war es
String a2 =" ab ";
.
Konstante + neue Zeichenfolge ("")
String a1 = "ab";
String a2 = "a" + new String("b");
System.out.println(a1 == a2); // false
- "ab" wird im konstanten Poolbereich erzeugt, und der Referenzwert a1, der auf "ab" zeigt, wird im Stapelbereich erzeugt.
- Der neue String ("") wird beim Kompilieren nicht finalisiert.
Daher wird zum Zeitpunkt der Ausführung "b" im Heap-Bereich erzeugt, und ferner wird der Heap-Bereich "ab" erzeugt.
- Infolgedessen sind a1 und a2 falsch, da sie unterschiedliche "ab" -Adressen enthalten.
Konstante + Referenzwert
String a1 = "ab";
String a2 = "b";
String a3 = "a" + a2;
System.out.println(a1 == a3); // false
- "ab" wird im konstanten Poolbereich erzeugt, und der Referenzwert a1, der auf "ab" zeigt, wird im Stapelbereich erzeugt.
- "b" wird im konstanten Poolbereich erzeugt, und der Referenzwert a2, der auf "ab" zeigt, wird im Stapelbereich erzeugt.
- Da a2 ein Referenzwert ist, wird er zur Kompilierungszeit nicht festgelegt.
Daher wird zum Zeitpunkt der Ausführung im Heap-Bereich "ab" generiert, und a3 zeigt darauf.
- Infolgedessen ist a1 ein konstanter Pool und a3 ein Heap-Bereich, sodass er falsch wird.
Konstante + Finale
String a1 = "ab";
final String a2 = "b";
String a3 = "a" + a2;
System.out.println(a1 == a3); // true
- Mit final wird a2 als Konstante betrachtet und a3 ist konstant + konstant = konstant.
Betrachtet man es mit dem Dekompiler, so wurde es wie folgt kompiliert.
String a1 = "ab";
String a2 = "b";
String a3 = "ab";
System.out.println(a1 == a3);
String.intern()
Eine Methode, die den konstanten Pool erweitern kann.
String-Instanz .intern ()
- Wenn der gleiche Wert im Konstantenpool vorhanden ist, geben Sie den Referenzwert zurück.
- Wenn im Konstantenpool nicht derselbe Wert vorhanden ist, generieren Sie einen Wert im Konstantenpool und geben Sie den Referenzwert zurück.
String a1 = "ab";
String a2 = new String("ab");
System.out.println(a1 == a2); // false
a2 = a2.intern();
System.out.println(a1 == a2); // true
- "ab" wird im konstanten Poolbereich erzeugt, und der Referenzwert a1, der auf "ab" zeigt, wird im Stapelbereich erzeugt.
- "ab" wird im Heap-Bereich erzeugt, und der Referenzwert a2, der auf "ab" zeigt, wird im Stapelbereich erzeugt.
- Falsch wird weggelassen.
- Da a2.intern () und "ab" im Konstantenpool vorhanden sind, geben Sie die "ab" -Adresse des Konstantenpools an a2 zurück.
- Sowohl a1 als auch a2 zeigen im kontinuierlichen Pool auf "ab", also ist es wahr.
Bonus: Warum String + nicht gut abschneidet
String s = null;
for(int i = 0; i < 100; ++i) {
s = s + "a";
}
Basierend auf der bisherigen Überprüfung
Da s in s +" a ";
eine Variable ist, wird bei jeder Ausführung ein neues Objekt erstellt und zerstört.