Java Referenzdatentypen?
Mir ist ein bestimmter Aspekt, und zwar der Sinn einer Referenz noch nciht ganz klar geworden:
Primitiver Datentyp:
int zahl = 8;
Hier wird ja mit der Deklarierung der Variable zahl eine Adresse für einen gerade freien Speicherplatz erzeugt und in diesem Speicherort der Wert der Variable, 8, abgelegt.
So wie in meiner Zeichnung:
Referenzdatentyp:
Mensch mensch1 = new Mensch(16); //16 = pAlter
Hier wird auch mit der Variable einem gerade freien Speicherplatz eine Adresse zugeordnet. Dann wird in dem freien Speicherplatz, glaube ich, nichts (kein Variablen Wert (new Mensch(16) ) ) abgelegt, sondern nur eine komplett andere Adresse. Folgt man dieser Adresse und guckt in dem durch sie verwiesenen Speicherplatz nach, findet man da unseren Variablen - Wert = new Mensch(16).
Wie in meiner Zeichnung hier:
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? Sprich: Wozu eine Referenz auf eine andere Adresse (ich glaube immer Referenz auf eine andere Adresse, vielleicht ist es aber auch in WIrklichkeit eine Referenz auf das neue Menschen Objekt?)? Warum nicht so wie beim primitiven Datentypen machen, also so wie bei meiner Zeichnung hier unten?:
omg, diese logik - aber es macht mir Spaß, zu programmieren und ich möchte alles unbedingt verstehen !😊
3 Antworten
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;
}
//...
}
Irgendwie funktioniert der Link https://imgur.com/D3fyxQMIch nicht, nehmen Sie/nimm diesen Link: https://imgur.com/D3fyxQM
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.
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).
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😌😀👍👏
Damit ist sehr wahrscheinlich der Pfeil bei meiner ersten Zeichnung gemeint, der von mensch2 ausgeht
Exakt!
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 ....
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
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
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.
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.
"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.
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😀👍