Java-Referenzmechanismus (Stack und Heap)

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.

Mechanismus zur Realisierung der Java-Referenz

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.

Unterschiede in der Beibehaltung von Objekten und primitiven Typwerten

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.

Verhalten bei der Übergabe an Methodenargumente

Beim Übergeben eines Objekts oder einer primitiven Typvariablen an ein Methodenargument Der Inhalt des Stapelbereichs wird in einen anderen Stapelbereich kopiert. 引数へ渡した時の挙動.png 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.

Quellcode-Beispiel

Um zu bestätigen, dass die bisher beschriebenen Inhalte korrekt sind, werden wir den Quellcode mit dem Ausgabeergebnis vergleichen.

Beispiel 1

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] 例1.png

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

Beispiel 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] 例2.png 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

Beispiel 3

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

Beispiel 4

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] スクリーンショット 2020-06-02 0.58.52.png 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

Beispiel 5

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] 例5.png 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

Java-Referenzmechanismus (Stack und Heap)
[Java] Stapelbereich und statischer Bereich
Java als Wert übergeben und als Referenz übergeben
Informationen zu primitiven Java-Typen und Referenztypen
Java-Basisdatentypen und Referenztypen
Java-Kern: HotSpot-Compiler und C-Heap
[Java] Berechnungsmechanismus, Operatoren und Typkonvertierung
Seitenzahllogik und Referenzcode (Java)
Java und JavaScript
XXE und Java
Java8-Methodenreferenz
JAVA Referenzmaterialien
Meine Java-Referenz
[Java] Filterstapelspuren
Getter und Setter (Java)
[Java] Thread und ausführbar
Java wahr und falsch
Organisieren Sie den Mechanismus von Java GC
[Java] Vergleich von Zeichenketten und && und ||
Java - Serialisierung und Deserialisierung
[Java] Argumente und Parameter
Informationen zum Java-Grunddatentyp- und Referenztypspeicher
timedatectl und Java TimeZone
[Java] Verzweigen und Wiederholen
[Java] Variablen- und Typtypen
Java (Klasse und Instanz)
[Java] Überladen und überschreiben
Lösen mit Ruby, Perl und Java AtCoder ABC 113 C Referenz
[Java] Unterschied zwischen der Zuweisung der Basistypvariablen und der Zuordnung der Referenztypvariablen
[Java] Unterschied zwischen Stapelüberlauffehler und Speichermangel
Studiere Java # 2 (\ mark and operator)
[Java] Integer-Wrapper-Klassenreferenz
Java Version 8 und neuere Funktionen
Basisdatentyp und Referenztyp
Java VB.net-Dienstreferenz auf halbem Weg
[Java] Unterschied zwischen == und gleich
Verschluss der Pony- und Referenzfähigkeit
Befehlsmechanismus und Verwaltungstools
[Java] Generics-Klasse und Generics-Methode
Java-Programmierung (Variablen und Daten)
Java-Ver- und Entschlüsselung PDF
Java und Iterator Teil 1 Externe Iterator Edition
Java if- und switch-Anweisungen
Definition und Instanziierung von Java-Klassen
Apache Hadoop und Java 9 (Teil 1)
[Java] Über String und StringBuilder
[Java] HashCode und gleich Überschreibung
☾ Java / Repeat-Anweisung und Repeat-Steueranweisung
Java-Methoden und Methodenüberladungen
Java Generics T und? Unterschied
Vor- und Nachteile von Java
Java (bedingte Verzweigung und Wiederholung)
Über Java-Paket und Import
Protokollieren Sie den Java NullPointerException-Stack-Trace
[Java] Laden Sie ein Bild hoch und konvertieren Sie es in Base64
C # und Java überschreiben Story
Java abstrakte Methoden und Klassen
Java während und für Anweisungen
Java-Kapselung und Getter und Setter
Mechanismus und Merkmale der in Java häufig verwendeten Collection-Implementierungsklasse