Java Referenzdatentypen?

3 Antworten

Vom Fragesteller als hilfreich ausgezeichnet
Was ich jetzt nicht so richtig verstehe ist, warum wird unser Variablenwert (unser neues menschen - objekt) unter einer anderen Adresse abgelegt, als der, der der Variable "mensch1"eigentlich zugeordnet wurde?

Damit du an anderer Stelle auf auf dasselbe Objekt verweisen kannst. Das Objekt wird quasi zentral gespiechert.

Außerdem kannst du so die Referenz auch unkompliziert auf ein anderes Objekt zeigen lassen, wenn du das möchtest.

Beispiel:

Spieler one = new Spieler();
Spieler two = new Spieler();
//...
for(int i = 0; i < rounds; ++i){
    Spieler current;
    if(i%2 == 0){
        current = one;
    }else{
        current = two;
    }
    //...
}
PrettyRANDOM 
Fragesteller
 07.10.2022, 11:52

"Damit du an anderer Stelle auf auf dasselbe Objekt verweisen kannst."

Hier ist mir nicht ganz klar geworden was Sie/du mit "Stelle" meinst/meinen. Meine Vermutung wäre, das "Stelle" eine andere Variable sein kann, so wie hier in meiner Zeichnung für "an anderer Stelle auf auf dasselbe Objekt verweisen":
https://imgur.com/8Nl2Tdn

Das ist jetzt ein Link, kein schädlicher. Imgur ist eine Website, mit der man Bilder von seinem Computer in einen Link umwandeln kann und auch so Bilder anzeigen lassen kann, wo gerade keine Bilder erlaubt sind, z.B. in diesem GF - Kommentar - Textfeld.

Und hier in addition meine Interpretation von ihrer Aussage "Außerdem kannst du so die Referenz auch unkompliziert auf ein anderes Objekt zeigen lassen":

https://imgur.com/D3fyxQMIch

Ich wollte mal ein Programm schreiben zum Test, das das Alter von mensch1 ausgibt. Nach meiner Zeichnung hier (https://imgur.com/D3fyxQM) zeigt mensch1 auf new Mensch(16) und new Mensch(18). Bei meinem Programm wird aber nur "18" ausgeben.

    public static void main(String[] args) {
Mensch mensch1 = new Mensch(16);
mensch1 = new Mensch(18);
System.out.println(mensch1.getAlter());
}

Anstatt "16 18)". Obwohl mensch1 doch auf beide verweist... Mein Prinzip (damit meine ich, wie ich die Referenzpfeile von mensch1 in meiner Zeichnung gezeigt habe) ist denke ich mal richtig, aber wie kann ich den über die Programmierung, wenn eine Variable mensch1 eine Referenz auf zwei Menschenobjekte referenziert, das so machen, dass mensch1 nicht nur das Alter von new Mensch(18) ausgeben kann sondern auch das Alter von new Mensch(16)? Dank der zwei Referenzen muss mensch1 doch auch auf die Attribute von beiden referenzierten Objekten zugreifen können.
Dankeschön aufjedenfall für Ihre/Deine Antwort😀👍

1
regex9  07.10.2022, 12:22
@PrettyRANDOM
Meine Vermutung wäre, das "Stelle" eine andere Variable sein kann, (...)

Ja, das ist damit gemeint.

Nach meiner Zeichnung hier (...) zeigt mensch1 auf new Mensch(16) und new Mensch(18

Eine Variable kann immer nur auf einen Wert zeigen, wobei der Wert selbst natürlich ein Wertebündel sein kann. Hier beispielsweise zeigt humans auf ein Array-Objekt. Dieses Objekt wiederum kennt Verweise auf maximal fünf andere Human-Objekte.

Human[] humans = new Humans[5];

Wenn du der Variable einen neuen Wert zuweist, merkt sie sich auch nur diesen neuen Wert.

1
Destranix  07.10.2022, 12:24
@PrettyRANDOM
Meine Vermutung wäre, das "Stelle" eine andere Variable sein kann

Genau!

Deine Zeichnung passt allerdings nicht. Der Pfeil sollte zur 34 hingehen. Dann sollte auch ersichtlich werden, wieso das Objekt an einer anderen Stelle liegt, eben damit verschiedene Variablen auf dieselbe Weise darauf verweisen können.

Und hier in addition meine Interpretation von ihrer Aussage "Außerdem kannst du so die Referenz auch unkompliziert auf ein anderes Objekt zeigen lassen":

Du kannst leicht den Link von 34 auf 40 umändern und dabei bleibt das 34 Objekt noch erhalten und andere variablen können weiterhin darauf zeigen.

Nach meiner Zeichnung hier (https://imgur.com/D3fyxQM) zeigt mensch1 auf new Mensch(16) und new Mensch(18). Bei meinem Programm wird aber nur "18" ausgeben.

Du kannst nur immer auf ein Objekt zeigen. Wenn du mensch1 die Referenz auf Mensch(18) zuweist, dann überschreibst du die Referenz auf Mensch(16).

0
PrettyRANDOM 
Fragesteller
 07.10.2022, 12:34
@Destranix

JA!😀👍👏(#Erfolgserlebnis)
"Der Pfeil sollte zur 34 hingehen."
Damit ist sehr wahrscheinlich der Pfeil bei meiner ersten Zeichnung gemeint, der von mensch2 ausgeht
"Dann sollte auch ersichtlich werden, wieso das Objekt an einer anderen Stelle liegt, eben damit verschiedene Variablen auf dieselbe Weise darauf verweisen können."
Ja😌😀👍👏

1
Destranix  07.10.2022, 12:52
@PrettyRANDOM
Damit ist sehr wahrscheinlich der Pfeil bei meiner ersten Zeichnung gemeint, der von mensch2 ausgeht

Exakt!

1

Es hat verschiedene Gründe warum es eine Referenz gibt.

So kann es bspw mehrere Referenzen auf das selbe Objekt geben. Ändert man über eine Referenz den Wert dieses Objektes ab, so ändert sich gleichzeitig für alle anderen Referenzen der Wert. Es gibt also eine Eindeutigkeit.

Das Objekt hinter Referenz kann weitere Informationen enthalten; so bspw neben dem Alter, die Größe oder das Gewicht. Ein Objekt ist also mehr als die Summe seiner Teile.

Tatsächlich wird bei einer Referenz nicht eine Adresse gehalten sondern im Normalfall ein sogenannter "Handler" mit weitergehenden Informationen; wird vielleicht ein wenig technisch. Wenn man eine Adresse mit einem Inhalt hat, so ist dies statisch. Hat man einen Handler so kann man den Inhalt auch auf Festplatte auslagern ("swappen"), dies im Handler vermerken und bei Bedarf wieder in den Internspeicher holen ....

Woher ich das weiß:Berufserfahrung – Startup zum weltweiten Unternehmen entwickelt.

Also tatsächlich empfinde ich die Art und Weise wie du das hier schreibst als ziemlich verwirrend...

Ich denke das worauf du hier anspielst ist die Pointer / Referenz Geschichte die man aber eher aus C++ kennt und in Java nicht so wirklich braucht.

Deshalb eine C++ erklärung:

Du hast 2 Arten von Datenstrukturen in welcher dein (Arbeits)-Speicher vorliegen kann, den Stack und den Heap. Da C++ anders als Java nicht über einen garbage-collector verfügt und sich um die speicherbereinigung daher nicht selbst kümmert, muss der Entwickler selbst Arbeitsspeicher vom Betriebssystem anfordern und auch wieder freigeben, sollte er den Heap als Speicher verwenden wollen. Ein Beispiel:

Class A {};

int main()
{
   A a; //Stack Objekt 
   A * a = new A(); //Heap Objekt
}

In Fall Nr 2 müsstest du dich jetzt um die Speicherbereinigung selbst kümmern, das ist auch der "Normalfall" in Java, nur dass dir diese Arbeit dann der Compiler abnimmt.

Auf den Heap kannst du so gesehen auch nicht direkt zugreifen, sondern nur über einen Pointer / eine Referenz. Das bedeutet, du hast in der Variable a im 2. Fall so wie du es auch in deiner Frage stehen hast nur einen Pointer, welcher auf die Stelle im Heap zeigt in welcher dein Objekt A abgespeichert worden ist.

Dass liegt einzig und alleine daran dass du auf den Heap anders als auf den Stack keinen direkten Zugriff hast, insofern verwendet man einen Pointer welcher auf die Entsprechende Stelle im Heap zeigt wo sich dein Objekt befindet.

Dass du dich das allerdings bei Java fragst verstehe ich nicht so ganz, weil dort prinzipiell jedes Objekt auf dem Heap erstellt wird (sieht man an dem new Keyword), du dich um die "Besonderheiten" damit aber nicht kümmern musst. Insofern würdest du auch weit kommen wenn du das ganze nicht verstehst.

Lg

PrettyRANDOM 
Fragesteller
 07.10.2022, 11:59

Achso (Ich habe das jetzt so verstanden:):
(Referenz)datentypen, wie z.B. Objekte, werden immer im Heap gespeichert, auf den man aber nur mit Referenzen/Pointern zugreifen kann. Primitive Datentypen werden im Stack gespeichert. Da kann man irgendwie direkt drauf zugreifen. Deshalb braucht man bei primitiven Datentypen keine Referenz

0
Valentin1720653  07.10.2022, 12:11
@PrettyRANDOM

Also in Java stimmt das, benutzerdefinierte Datentypen werden immer auf dem Heap erstellt. In C++ kann man es selbst entscheiden, der Heap ist aber deutlich größer als der Stack, daher ist es notwendig bei geößeren Programmen den Heap zu verwenden.

Und der Rest ist dann korrekt. Ist ein Objekt auf dem Heap gespeichert, dann brauchst du über den Stack einen Pointer / eine Referenz die auf das Objekt des heaps verweist, da du nicht auf direktem Wege auf diese zugreifen kannst.

Daher hast du diesen "Zwischenschritt" drin den du in deiner Frage nicht verstanden hast.

0
Destranix  07.10.2022, 12:26
@Valentin1720653
der Heap ist aber deutlich größer als der Stack

Nicht unbesingt. Die können auch einfach aufeinander zuwachsen und hätten damit dieselbe Kapazität.

0