Ich denke, dass es nicht wirklich hilfreich ist, über Übergabe per Referenz vs. Übergabe per Wert zu streiten.
Wenn du sagst, dass Java übergibt-wie-auch-immer ist, gibst du keine vollständige Antwort. Hier sind einige zusätzliche Informationen, die hoffentlich helfen zu verstehen, was tatsächlich im Speicher passiert.
Kurzer Kurs über Stack/Heap, bevor wir zur Java-Implementierung kommen: Werte kommen ordentlich auf den Stack und gehen wieder runter, wie ein Stapel Teller in einer Cafeteria. Speicher im Heap (auch bekannt als dynamischer Speicher) ist chaotisch und unorganisiert. Die JVM findet einfach Platz, wo sie kann, und gibt ihn frei, wenn die Variablen, die ihn benutzen, nicht mehr benötigt werden.
Also. Lokale Primitiven kommen auf den Stack. Also wird dieser Code:
int x = 3;
float y = 101.1f;
boolean binIchToll = true;
zu diesem Ergebnis führen:
![Primitiven auf dem Stack]()
Wenn du ein Objekt deklarierst und instanziierst, dann geht das tatsächliche Objekt auf den Heap. Was kommt auf den Stack? Die Adresse des Objekts auf dem Heap. C++-Programmierer würden dies als Zeiger bezeichnen, aber einige Java-Entwickler sind gegen das Wort "Zeiger". Wie auch immer. Wisse nur, dass die Adresse des Objekts auf dem Stack liegt.
So:
int probleme = 99;
String name = "Jay-Z";
![ein Problem weniger!]()
Ein Array ist auch ein Objekt, also geht es auch auf den Heap. Und was ist mit den Objekten im Array? Sie bekommen ihren eigenen Heap-Speicher, und die Adresse jedes Objekts wird im Array gespeichert.
JButton[] marxBros = new JButton[3];
marxBros[0] = new JButton("Groucho");
marxBros[1] = new JButton("Zeppo");
marxBros[2] = new JButton("Harpo");
![Marx-Brothers]()
Also, was wird übergeben, wenn du eine Methode aufrufst? Wenn du ein Objekt übergibst, dann übergibst du tatsächlich die Adresse des Objekts. Einige würden sagen, der "Wert" der Adresse, und einige sagen, es ist nur eine Referenz auf das Objekt. Dies ist der Ursprung des heiligen Krieges zwischen den Vertretern von "Referenz" und "Wert". Wie auch immer du es nennst, wichtig ist nur, dass du verstehst, dass die Adresse des Objekts übergeben wird.
private static void rufen(String name){
System.out.println("Da geht " + name + "!");
}
public static void main(String[] args){
String seinName = "John J. Jingleheimerschmitz";
String meinName = seinName;
rufen(meinName);
}
Ein String wird erstellt und Speicherplatz dafür auf dem Heap reserviert, und die Adresse des Strings wird auf dem Stack gespeichert und mit dem Bezeichner seinName
versehen. Da die Adresse des zweiten Strings die gleiche wie die des ersten ist, wird kein neuer String erstellt und kein neuer Heap-Speicher reserviert, aber ein neuer Bezeichner wird auf dem Stack erstellt. Dann rufen wir rufen()
: ein neuer Stackrahmen wird erstellt und ein neuer Bezeichner, name
, wird erstellt und der bereits vorhandene String zugewiesen.
![La da di da da da da]()
Also, Wert, Referenz? Du sagst "Kartoffel".
6 Stimmen
Wir würden eher sagen, dass eine Variable, die "per Referenz übergeben" wird, verändert werden kann. Der Begriff taucht in Lehrbüchern auf, weil Sprachtheoretiker eine Möglichkeit brauchten, um zu unterscheiden, wie Sie primitive Datentypen (int, bool, byte) von komplexen und strukturierten Objekten (Array, Streams, Klasse) behandeln - das heißt, die möglicherweise ungebundene Speicherzuweisung.
6 Stimmen
Ich möchte darauf hinweisen, dass Sie sich in den meisten Fällen keine Gedanken darüber machen müssen. Ich habe viele Jahre lang Java programmiert, bis ich C ++ gelernt habe. Bis zu diesem Zeitpunkt hatte ich keine Ahnung, was Übergabe nach Referenz und Übergabe nach Wert sind. Die intuitive Lösung hat immer für mich funktioniert, deshalb ist Java eine der besten Sprachen für Anfänger. Wenn Sie sich also gerade Sorgen machen, ob Ihre Funktion eine Referenz oder einen Wert benötigt, übergeben Sie sie einfach so, wie sie ist, und es wird alles in Ordnung sein.
73 Stimmen
Java übergibt die Referenz nach Wert.
21 Stimmen
Ganz knapp gesagt entsteht diese Verwirrung, weil in Java alle Nicht-Primitive Datentypen durch Referenzen behandelt / zugegriffen werden. Allerdings wird immer nach Wert übergeben. Daher wird für alle Nicht-Primitive Typen die Referenz nach seinem Wert übergeben. Auch alle primitiven Typen werden nach Wert übergeben.
6 Stimmen
Ich fand das ziemlich hilfreich: baeldung.com/java-pass-by-value-or-pass-by-reference
1 Stimmen
Es ist der Unterschied zwischen foo.bar(sth) und foo = sth. Im ersten Fall wird das Objekt mit der Variablen, die darauf zeigt, geändert, und die Variable selbst, die auf das Objekt zeigt, wurde nicht geändert. Im zweiten Fall hingegen wurde die Variable selbst, die auf das Objekt zeigt, geändert und zeigt nun auf ein anderes Objekt. Wenn Sie einen Hintergrund in C++ haben: Ein Zeiger ist eine Variable, die eine Speicheradresse enthält, während eine Referenz die gleiche Speicheradresse wie das von ihr referenzierte Element hat. In Java ist tatsächlich ein Zeiger nach Wert übergeben, aber Javaistas nennen es Referenz!
3 Stimmen
Was würde es also bedeuten, wenn eine Sprache eine Referenz nicht nach Wert übergeben würde? Pointer auf Pointer übergeben? Gibt es Sprachen, die so etwas tun? Geben Sprachen wie C/C++ nicht auch Referenzen und Pointer nach Wert weiter??
1 Stimmen
Da Java eine objektorientierte Sprache ist und Objekte per Referenz übergeben werden, entsprechen Änderungen des Objekts gemäß langjährig etablierter Semantik dem Original. Es ist nicht klar, wie sich dieser "pass-by-value"-Unsinn so weit verbreiten konnte.
2 Stimmen
@SamGinrich Java ist immer durch Wertübertragung. Wenn Sie dieses grundlegende Konzept nicht verstehen, das bei weitem nicht so "unsinnig" ist, wie Sie es nennen, empfehle ich Ihnen, die am meisten hoch bewerteten Antworten hier zu lesen, bis Sie verstehen, warum.
0 Stimmen
Für diejenigen, die eine Videoerklärung bevorzugen youtu.be/fL-nXdKWwOg
1 Stimmen
Diese "Objekte werden nach Wert übergeben"-Sache ist irreführend. Referenzen zu Objekten werden übergeben. Nicht kopierte/verschobene Werte von Objekten. Dass die Referenzen selbst nach Wert übergeben werden, ist ein winziges Detail von nicht viel Interesse.
0 Stimmen
@Dalija Prasnikar ... diese Muggelsprache allein! Java ist im Grunde genommen eine objektorientierte Programmiersprache, kein Modus zum Übergeben von Objekten. Selbst wenn Java keine Dereferenzierung unterstützt, ist die Idee, sie als Grundlage für konzeptionelle Diskussionen zu nehmen, genauso fruchtbar wie wenn ein Vegetarier eine Rede bei einer Metzgergilde hält.
1 Stimmen
@SamGinrich Du mischst Äpfel und Birnen. Die Programmiersprachenparadigma allein ist nicht direkt mit den Mechanismen verbunden, die eine Sprache zur Parameterübergabe verwendet. Jeder, der die Funktionsweise von Compilern und Sprachenentwicklung kennt, weiß den Unterschied. Die Terminologie ist universell, weil sie denjenigen, die wissen, was sie bedeutet, eine Bedeutung vermittelt. Nur weil du es ablehnst, die Definition zu lernen, weil es dir keinen Sinn ergibt, bedeutet das nicht, dass es keinen Wert für andere hat, die es verstehen. Ich schlage vor, dass du die beste Antwort sehr sorgfältig liest.
0 Stimmen
@Dalija Prasnikar Sie sind sehr weise und verständnisvoll und haben die Definition, die Ihnen gegeben wurde, fleißig gelernt.
1 Stimmen
@SamGinrich Es geht nicht darum, die Definition wie ein Papagei auswendig zu lernen. Es geht darum zu verstehen, was sie bedeutet und warum solche Definitionen benötigt werden. Definitionen beziehen sich nicht nur auf eine einzige Sprache, sondern auf alle Sprachen. Sie sind wichtig, weil sie das genaue Verhalten in einfachen Worten beschreiben. Wenn man die Worte verdreht, verliert man die präzise Beschreibung dessen, was passiert. Es ist wie in der Mathematik, wo wir einige Definitionen haben, die die Grundlage für alles bilden. Man könnte sagen, dass einige willkürlich gewählt sind und wir die Mathematik auch aus leicht unterschiedlichen begriffen entwickeln könnten, aber dann würde auch alles andere in der Mathematik sich ändern.
0 Stimmen
@Dalija Prasnikar Wie ich oben sagte: "Java ist keine gute Basis, um Dereferenzierung zu verstehen"; trotzdem sind Sie frei, dies zu behaupten. Ich wäre vorsichtig, jemanden als ungebildet zu betrachten, der eine konsistente Meinung zu einem Thema hat.
1 Stimmen
@SamGinrich Konsequenz bedeutet nicht automatisch Wissen. Du kannst konsequent behaupten, dass die Erde flach ist, und du würdest immer noch falsch liegen.
4 Stimmen
Bevor du eine neue Antwort postest, bedenke, dass es bereits 93+ Antworten auf diese Frage gibt. Stelle sicher, dass deine Antwort Informationen enthält, die nicht unter den bereits vorhandenen Antworten zu finden sind. Danke!
0 Stimmen
@Dalija Prasnikar Das Dogma "Java ist pass-by-value" ist ziemlich konsistent, solange man nicht die Grammatik betrachtet. Ich habe gesehen, dass du dich frei gefühlt hast, Beiträge zu löschen, die dieser Regel nicht folgen, dies ist keine Haltung, die die Absicht einer Diskussion widerspiegelt, die offen für Kritik ist. Es gibt gebildete Menschen mit anderen Denkweisen, auch zum Thema. Es sollten bessere Gründe für die Zensur geben und ich hoffe, dass du sie findest.
1 Stimmen
@SamGinrich Meine Moderationsaktivitäten basieren nicht darauf, was mir gefällt oder nicht, sondern auf Korrektheit. Wenn du jedoch Probleme mit den Handlungen einer Person hast oder glaubst, dass ein Beitrag nicht angemessen behandelt wurde, kannst du das immer im Stack Overflow Meta ansprechen. Was diese Frage/Antwort betrifft, habe ich nichts Neues zu sagen, was ich nicht schon gesagt habe.