Ich hatte die Gelegenheit, den Mechanismus der Java-Referenz für meine Junioren anhand des Stapelbereichs und des Java-Heap-Bereichs zu erläutern. Ich erinnere mich, dass ich über Java-Referenzen verwirrt war, als ich die Beziehung zwischen diesen Bereichen nicht kannte. Es ist eine gute Gelegenheit, also werde ich es in einem Artikel zusammenfassen.
In der JVM sind ein Stapelbereich und ein Java-Heap-Bereich vorhanden, um die Java-Referenz zu realisieren. Java-Referenzen werden von diesen beiden Bereichen realisiert.
Bereichsname | Überblick |
---|---|
Stapelbereich | Es enthält hauptsächlich Referenzinformationen zum Heap-Bereich. Es enthält auch den Wert des primitiven Typs. |
JAVA-Haufenbereich | Der tatsächliche Wert des Objekts wird in diesem Speicher gespeichert. |
Java-Objekte (Klasse, Array usw.) enthalten Heap-Bereichsreferenzinformationen im Stapelbereich. Der Istwert wird im Heap-Bereich gespeichert.
Primitive Typen haben eine andere Speicherverwaltung als Objekte. Wenn Sie eine primitive Typvariable erstellen, enthält diese den Wert im Stapelbereich.
Beim Übergeben eines Objekts oder einer primitiven Typvariablen an ein Methodenargument Der Inhalt des Stapelbereichs wird in einen anderen Stapelbereich kopiert. Im obigen Fall ist die Referenz von argA dieselbe wie die Variable a. Das Ändern des referenzierten Werts in method1 wirkt sich auch auf die Variable a aus.
Um zu bestätigen, dass die bisher beschriebenen Inhalte korrekt sind, werden wir den Quellcode mit dem Ausgabeergebnis vergleichen.
Quellcode
package test;
class Class1 {
String id;
int value;
}
public class Test {
public static void main(String[] args) {
Class1 a = new Class1();
a.id = "ID1";
a.value = 1;
//Bedienung [1]
Class1 b = a;
//Bedienung [2]
b.id = "ID2";
b.value = 2;
//Bedienung [3]
b = null;
//Was ist der Wert, der hier ausgegeben wird?
System.out.println("id:" + a.id);
System.out.println("value:" + a.value);
}
}
[Betriebsdetails]
Durch die Operation [2] wird auch der Wert des Referenzziels der Variablen a neu geschrieben. Operation [3] löscht den Verweis auf Variable b, wirkt sich jedoch nicht auf Variable a mit einem anderen Stapel aus. Daher sind die Ausgabeinhalte wie folgt.
Ausgabeergebnis
id:ID2
value:2
Quellcode
package test;
class Class1 {
String id;
int value;
}
public class Test {
public static void main(String[] args) {
Class1 a = new Class1();
a.id = "ID1";
a.value = 1;
//Bedienung [1]
method1(a);
//Was ist der Wert, der hier ausgegeben wird?
System.out.println("id:" + a.id);
System.out.println("value:" + a.value);
}
private static void method1(Class1 argA) {
//Bedienung [2]
argA.id = "ID2";
argA.value = 2;
}
}
[Betriebsdetails] Durch die Operation [2] wird auch der Wert des Referenzziels der Variablen a neu geschrieben. Daher sind die Ausgabeinhalte wie folgt.
Ausgabeergebnis
id:ID2
value:2
Quellcode
package test;
class Class1 {
String id;
int value;
}
public class Test {
public static void main(String[] args) {
Class1 a = new Class1();
a.id = "ID1";
a.value = 1;
//Bedienung [1]
method1(a);
//Was ist der Wert, der hier ausgegeben wird?
System.out.println("1. Mal =========");
System.out.println("id:" + a.id);
System.out.println("value:" + a.value);
//Bedienung [2]
method2(a);
//Was ist der Wert, der hier ausgegeben wird?
System.out.println("Zweites Mal =========");
System.out.println("id:" + a.id);
System.out.println("value:" + a.value);
}
private static void method1(Class1 argA) {
argA = null;
}
private static void method2(Class1 argA) {
argA = new Class1();
argA.id = "ID2";
argA.value = 2;
}
}
[Betriebsdetails] Wie in Beispiel 2 übergeben wir die Variable a als Methodenargument. Die Methode [1] weist null zu und löscht die Referenz von argA, wirkt sich jedoch nicht auf die Variable a mit einem anderen Stapel aus. Da die Funktionsweise [2] eine neue Klasse 1 ist, hat sich das Referenzziel in die Variable a geändert. Das Festlegen der ID- und Wertwerte nach Änderung der Referenz wirkt sich nicht auf die Variable a aus. Daher sind die Ausgabeinhalte wie folgt.
Ausgabeergebnis
1. Mal =========
id:ID1
value:1
Zweites Mal =========
id:ID1
value:1
Quellcode
package test;
public class Test {
public static void main(String[] args) {
int a = 1;
//Bedienung [1]
int b = a;
//Bedienung [2]
b = 99;
//Was ist der Wert, der hier ausgegeben wird?
System.out.println("1. Mal =========");
System.out.println("a:" + a);
System.out.println("b:" + b);
//Bedienung [3]
method1(a);
//Was ist der Wert, der hier ausgegeben wird?
System.out.println("Zweites Mal =========");
System.out.println("a:" + a);
}
private static void method1(int argA) {
//Bedienung [4]
argA = 99;
}
}
[Betriebsdetails] Jede primitive Typvariable enthält unabhängig einen Wert im Stapelbereich. Jede Operation wirkt sich nicht auf eine andere Variable aus. Daher sind die Ausgabeinhalte wie folgt.
Ausgabeergebnis
1. Mal =========
a:1
b:99
Zweites Mal =========
a:1
Quellcode
package test;
public class Test {
public static void main(String[] args) {
int a = 0;
//Bedienung [1]
int[] b = {a};
//Bedienung [2]
method1(b);
//Was ist der Wert, der hier ausgegeben wird?
System.out.println("a:" + a);
System.out.println("b[0]:" + b[0]);
}
private static void method1(int[] argB) {
//Bedienung [3]
argB[0] = 99;
}
}
[Betriebsdetails] Selbst wenn es sich um einen primitiven Typ handelt, wird sein Wert im Heap-Bereich gespeichert, wenn Sie ihn als Array beibehalten. Das Ändern des Arrays argB in Operation [3] wirkt sich auf das Array b aus, das dasselbe Referenzziel hat. Daher sind die Ausgabeinhalte wie folgt.
Ausgabeergebnis
a:0
b[0]:99
Recommended Posts