Ist Java "pass-by-reference" oder "pass-by-value"?
Ich dachte immer, Java war pass-by-reference.
Jedoch, ich habe gesehen, ein paar blog-posts (zum Beispiel, dieser blog), die behaupten, dass es nicht so ist.
Ich glaube nicht, ich verstehe die Unterscheidung, die Sie machen.
Was ist die Erklärung?
Ich glaube, dass viel von der Verwirrung über diese Frage hat mit der Tatsache zu tun, dass unterschiedliche Menschen haben unterschiedliche Definitionen des Begriffs "Referenz". Besucher aus einem C++ - hintergrund davon ausgehen, dass "Referenz" muss bedeuten, was es bedeutete, in C++, Menschen aus einem C-hintergrund übernehmen "Referenz" muss die gleiche sein, wie "Zeiger" in Ihrer Sprache, und so weiter. Ob es korrekt ist zu sagen, dass Java geht durch die Referenz hängt wirklich davon ab, was ist gemeint mit "Referenz".
Ich versuche, Sie zu nutzen konsequent die Terminologie gefunden auf Evaluation-Strategie Artikel. Es sollte angemerkt werden, dass, obwohl die Artikel Punkte out die Bedingungen variieren je nach Gemeinschaft, es betont, dass die Semantik für
Können Sie gehen und setzen Sie Ihren Kommentar auf einem RIESIGEN billboard, oder was? Das ist das ganze Problem in einer nussschale. Und es zeigt, dass diese ganze Sache ist Semantik. Wenn wir nicht damit einverstanden sind, auf der Basis der definition einer Referenz wird, dann werden wir nicht einig über die Antwort auf diese Frage 🙂
Ich denke, die Verwirrung ist "pass by reference" versus "Referenz-Semantik". Java ist pass-by-value mit Referenz-Semantik.
während Sie absolut richtig, die Leute kommen von C++ instinktiv eine andere intuition hinsichtlich der Begriff "Referenz -", ich persönlich glaube, der Körper ist mehr begraben in der "von". "Vorbei" ist verwirrend, es ist absolut Verschieden von "Vorbei" in Java. In C++, allerdings ist es umgangssprachlich nicht. In C++ kann man sagen, "übergabe einer Referenz", und es ist so verstanden, dass es passieren
Ich versuche, Sie zu nutzen konsequent die Terminologie gefunden auf Evaluation-Strategie Artikel. Es sollte angemerkt werden, dass, obwohl die Artikel Punkte out die Bedingungen variieren je nach Gemeinschaft, es betont, dass die Semantik für
call-by-value
und call-by-reference
unterscheiden sich in einer sehr entscheidenden Art und Weise. (Ich persönlich bevorzuge, um mit call-by-object-sharing
in diesen Tagen über call-by-value[-of-the-reference]
, als dies beschreibt die Semantik auf einem hohen Niveau und nicht zu Konflikten mit call-by-value
, was ist die zugrunde liegende Implementierung.)Können Sie gehen und setzen Sie Ihren Kommentar auf einem RIESIGEN billboard, oder was? Das ist das ganze Problem in einer nussschale. Und es zeigt, dass diese ganze Sache ist Semantik. Wenn wir nicht damit einverstanden sind, auf der Basis der definition einer Referenz wird, dann werden wir nicht einig über die Antwort auf diese Frage 🙂
Ich denke, die Verwirrung ist "pass by reference" versus "Referenz-Semantik". Java ist pass-by-value mit Referenz-Semantik.
während Sie absolut richtig, die Leute kommen von C++ instinktiv eine andere intuition hinsichtlich der Begriff "Referenz -", ich persönlich glaube, der Körper ist mehr begraben in der "von". "Vorbei" ist verwirrend, es ist absolut Verschieden von "Vorbei" in Java. In C++, allerdings ist es umgangssprachlich nicht. In C++ kann man sagen, "übergabe einer Referenz", und es ist so verstanden, dass es passieren
swap(x,y)
test.InformationsquelleAutor |
Du musst angemeldet sein, um einen Kommentar abzugeben.
Java ist immer pass-by-value. Leider, wenn wir an den Wert eines Objekts übergeben wir die Referenz. Das ist verwirrend für Anfänger.
Geht es so:
Im obigen Beispiel
aDog.getName()
wird noch zurück"Max"
. Der WertaDog
innerhalbmain
wird nicht verändert in der Funktionfoo
mit derDog
"Fifi"
als die Objekt-Referenz wird als Wert übergeben. Wenn es durch Verweis übergeben, dann dieaDog.getName()
immain
zurückkehren würde"Fifi"
nach dem Aufruffoo
.Ebenfalls:
Im obigen Beispiel
Fifi
ist der name des Hundes nach Aufruffoo(aDog)
weil das Objekt wurde innerhalb vonfoo(...)
. Alle Operationen, diefoo
führt aufd
sind, so dass für alle praktischen Zwecke, Sie sind durchgeführtaDog
, aber es ist nicht möglich, ändern Sie den Wert der VariablenaDog
selbst.Aber es gibt einen feinen Unterschied. Blick auf das erste Beispiel. Wenn es rein der Verweis übergeben, aDog.würde der name "Fifi". Es ist nicht die Referenz, die Sie bekommen ist ein Wert-Verweis, wenn Sie überschrieben wird wiederhergestellt, wenn das verlassen der Funktion.
Nein, in Java ist alles von Wert übergeben wird. Primitive sind durch Wert übergeben und Objekt-Referenzen als Wert übergeben werden. Die Objekte selbst sind nie an eine Methode übergeben, aber die Objekte werden immer im heap und nur einen Verweis auf das Objekt an die Methode übergeben wird.
Mein Versuch ein guter Weg, um zu visualisieren Objekts: stellen Sie sich einen Ballon. Aufrufen einer fxn ist wie tieing eine zweite Schnur um den Ballon und die übergabe der Zeile an den fxn. parameter = new Ballon() cut, string und erstellen Sie einen neuen Ballon (dies hat jedoch keine Auswirkung auf die original-Ballon). parameter.pop() pop, obwohl, denn es folgt der string, auf den gleichen, ursprünglichen Ballon. Java ist pass-by-value, aber der übergebene Wert ist nicht tief, es ist auf der höchsten Ebene, d.h. ein primitiver oder ein Zeiger ist. Nicht zu verwechseln, mit einem tiefen pass-by-value, wo das Objekt ist vollständig kloniert und übergeben.
Was ist verwirrend ist, dass die Objekt-Referenzen sind eigentlich Zeiger. Am Anfang SONNE nannte Sie die Zeiger. Dann marketing darüber informiert, dass "Zeiger" war ein böses Wort. Aber Sie sehen immer noch das "richtige" Nomenklatur in NullPointerException.
InformationsquelleAutor
Ich habe gerade bemerkt, dass du die referenzierte meine Artikel.
Die Java-Spec sagt, dass alles in Java ist pass-by-value. Es gibt keine solche Sache als "pass-by-reference" in Java.
Den Schlüssel zum Verständnis ist, dass so etwas wie
ist nicht ein Hund; es ist tatsächlich ein Zeiger ein Hund.
Was das bedeutet, ist, wenn Sie
sind Sie im wesentlichen vorbei an der Adresse der erstellten
Dog
Objekt derfoo
Methode.(Ich sage im wesentlichen, weil Java-Zeiger sind keine direkten Adressen, aber es ist am einfachsten daran zu denken, dass Art und Weise)
Angenommen, die
Dog
Objekt befindet sich an der Speicheradresse 42. Dies bedeutet, dass wir pass-42-Methode.wenn die Methode definiert wurden, als
schauen was passiert.
someDog
auf den Wert 42someDog
ist, folgte denDog
es Punkte (dieDog
Objekt an der Adresse 42)Dog
(die man an der Adresse 42) wird gebeten, seinen Namen ändern zu MaxDog
erstellt. Lassen Sie uns sagen, er ist unter der Adresse 74someDog
74Dog
es Punkte (dieDog
Objekt an der Adresse 74)Dog
(die man unter der Adresse 74) wird gebeten, seinen Namen ändern zu RowlfLassen Sie uns nun darüber nachdenken, was passiert außerhalb der Methode:
Hat
myDog
ändern?Da ist der Schlüssel.
Wenn man bedenkt, dass
myDog
ist ein Zeiger, und nicht eine tatsächlicheDog
ist die Antwort: NEIN.myDog
immer noch den Wert 42; es ist noch auf der original -Dog
(aber beachten Sie, dass wegen der Zeile "AAA", dessen name ist nun "Max" - immer noch der gleiche Hund;myDog
's Wert hat sich nicht geändert.)Es ist vollkommen gültig zu Folgen eine Adresse ein, und ändern, was am Ende von ihm; dass ändert sich nicht die variable, allerdings.
Java funktioniert genau wie C. Sie weisen einen Zeiger, übergeben Sie den Zeiger auf eine Methode, Folgen Sie den Zeiger in die Methode und die Daten ändern, auf die verwiesen wurde. Sie können jedoch nicht ändern, der pointer verweist.
In C++, Ada, Pascal und anderen Sprachen, die Unterstützung von pass-by-reference, können Sie tatsächlich ändern Sie die variable, die übergeben wurde.
Wenn Java hatte pass-by-reference-Semantik, die
foo
Methode, die wir oben definiert sind, geändert haben würde, womyDog
zeigte, wenn es zugewiesensomeDog
auf der Linie BBB.Denke, Referenz-Parameter, die als Aliase für die variable übergeben. Wenn der alias zugeordnet ist, so ist die variable, die übergeben wurde.
Sie sind falsch, imho. "Wenn man bedenkt, dass myDog ist ein Zeiger, und nicht eine tatsächliche Hund, die Antwort ist NEIN. myDog hat immer noch den Wert 42; es ist noch auf der original-Hund." myDog hat den Wert 42, aber sein name-argument enthält jetzt "Max", eher als "Rover" auf // AAA-Linie.
Denken Sie an es auf diese Weise. Hat jemand die Adresse von Ann Arbor, MI (meine Heimatstadt, GEHEN Sie BLAU!) auf ein Stück Papier namens "annArborLocation". Kopieren Sie es auf ein Stück Papier namens "myDestination". Sie können drive-in "myDestination" und einen Baum Pflanzen. Sie mag sich geändert haben, etwas über die Stadt an dieser Stelle, aber es ändert sich nicht die LAT/LON-das war geschrieben auf Papier. Sie können ändern Sie die LAT/LON auf "myDestination" aber es ändert sich nicht "annArborLocation". Hilft das?
Stanchfield: ich lese Ihre Artikel vor etwa einem Jahr und es half wirklich klar, was sich für mich. Danke! Darf ich demütig vorschlagen, eine kleine Ergänzung: man sollte erwähnen, dass es eigentlich einen bestimmten Begriff für diese form von "call-by-value, wo der Wert ist eine Referenz", die erfunden wurde von Barbara Liskov für die Beschreibung der Evaluierung der Strategie Ihres CLU Sprache im Jahre 1974, um Verwirrung zu vermeiden, wie die, die Ihre Artikel Adressen: call-by-sharing (auch call-by-object-sharing oder auch einfach call-by-object), was so ziemlich perfekt beschreibt die Semantik.
Die C/C++ - Sprachen nicht besitzen das Konzept eines "Zeiger". Es gibt andere Sprachen, die Zeiger verwenden, aber tun nicht zulassen, dass die gleichen Arten der manipulation von Zeigern, die C/C++ ermöglichen. Java hat Zeiger; Sie sind nur geschützt gegen Unwesen.
InformationsquelleAutor
Java übergibt immer Argumente per Wert und NICHT per Referenz.
Lassen Sie mich erklären dies durch eine Beispiel:
Ich erkläre dies in den Schritten:
Deklaration einer Referenz namens
f
TypFoo
und ordnen Sie ein neues Objekt vom TypFoo
mit einem Attribut"f"
.Aus der Seite der Methode, eine Referenz vom Typ
Foo
mit einem Namena
deklariert ist und es ursprünglich zugewiesenennull
.Wie Sie die Methode aufrufen
changeReference
, die Referenza
zugewiesen werden, das Objekt wird als argument übergeben.Deklaration einer Referenz namens
b
TypFoo
und ordnen Sie ein neues Objekt vom TypFoo
mit einem Attribut"b"
.a = b
macht eine neue Zuordnung zu der Referenza
, nichtf
, des Objekts, dessen Attribut ist"b"
.Als Sie rufen
modifyReference(Foo c)
Methode, eine Referenzc
erstellt und zugewiesen das Objekt mit Attribut"f"
.c.setAttribute("c");
ändert das Attribut des Objekts, das als Referenzc
Punkte, um es, und es ist dasselbe Objekt, Referenzf
Punkte.Ich hoffe, Sie verstehen jetzt, wie die übergabe von Objekten als Argumente funktioniert in Java 🙂
Es ist eine schöne Erklärung, aber wenn
a
Punkte auf das gleiche Objekt wief
(und nie bekommt seine eigene Kopie des Objektsf
Punkte), beliebige änderungen an dem Objekt mita
ändern solltef
aswell (da Sie beide arbeiten mit dem gleichen Objekt), so irgendwanna
muss seine eigene kopieren des Objektsf
Punkte zu.wenn 'a' Punkte, um das gleiche Objekt 'f' auch Punkte an, dann wird jede änderung an diesem Objekt per 'a' ist auch beobachtbar, über 'f', ABER ES ändert sich NICHT, 'f'. 'f' noch Punkte auf das gleiche Objekt. Sie können völlig verändern das Objekt, aber Sie können nie ändern, was 'f' Punkte zu. Dies ist das grundlegende Problem, dass für einige Grund dafür, dass manche Menschen einfach nicht verstehen können.
Dies ist die beste Erklärung, die ich gefunden habe. Übrigens, was über die grundlegende situation? Zum Beispiel, das argument muss einen int-Typ ist, tut es immer noch passieren die Kopie einer int-Variablen zu den Argumenten?
Gut erklärt. Jetzt kann ich sagen, ja. Der name des Parameters wird benutzt, um auf die verschiedenen Standorte. So seine paas-by-value ?
InformationsquelleAutor
Dies wird Ihnen einige Einblicke, wie Java eigentlich funktioniert bis zu dem Punkt, dass in Ihrem nächsten Diskussion über Java übergabe per Referenz oder als Wert übergeben werden, werden Sie nur lächeln 🙂
Schritt eins bitte löschen aus deinen Geist, das Wort, das fängt mit 'p' "_ _ _ _ _ _ _", vor allem, wenn Sie kommen aus anderen Programmiersprachen. Java und 'p' kann nicht geschrieben werden, im gleichen Buch, im forum, oder auch txt.
Schritt zwei denken Sie daran, dass, wenn Sie übergeben Sie ein Objekt in eine Methode, die Sie übergeben die Objekt-Referenz und nicht das Objekt selbst.
Nun denken, was ein Objekt-Referenz/variable hat/ist:
In den folgenden (bitte nicht versuchen, zu kompilieren/ausführen...):
Was passiert?
Ein Bild sagt mehr als tausend Worte:
Beachten Sie, dass die anotherReferenceToTheSamePersonObject Pfeile, die darauf gerichtet ist, das Objekt und nicht auf die variable person!
Wenn Sie nicht, um es sich dann vertraut mir einfach-und denken Sie daran, dass es besser ist, zu sagen, dass Java ist pass-by-value. Gut, pass by reference value. Oh gut, noch besser ist übergeben-von-Kopie-von-den-Variablen-Wert! 😉
Nun fühlen Sie sich frei, mich hassen, aber beachten Sie, dass angesichts dieser es gibt keinen Unterschied zwischen der Weitergabe primitive Datentypen und Objekte wenn man über die Methode Argumente.
Du immer übergeben Sie eine Kopie der bits der Wert der Referenz!
Natürlich können Sie schneiden Sie es kurz und einfach sagen, dass Java ist pass-by-value!
public void foo(Car car){ ... }
,car
lokalenfoo
und es enthält die heap-Position des Objekts? Also, wenn ich das änderncar
's-Wert voncar = new Car()
es wird auf verschiedene Objekt auf dem heap? und wenn ichcar
's-Eigenschaft valu durchcar.Color = "Red"
, das Objekt im heap zeigtecar
geändert werden. Auch ist es das gleiche in C#? Bitte Antworten! Danke!Bringst du Sie mir, bitte sagen Sie nicht das Wort wieder! 😉 Achtung, ich könnte diese Frage beantwortet haben, ohne zu sagen, 'Referenz' als gut. Es ist ein Terminologie-Problem und 'p' s machen es noch schlimmer. Mir und Scot haben unterschiedliche Ansichten zu diesem leider. Ich denke, du hast, wie es funktioniert in Java, jetzt können Sie nennen es pass by value, by-object-sharing, von-Kopie-von-den-Variablen-Wert, oder fühlen Sie sich frei zu kommen mit etwas anderem! Ich weiß nicht wirklich, wie lange, wie Sie kam, wie es funktioniert und was in einer variable vom Typ Object: nur eine Postfach-Adresse! 😉
Klingt wie Sie nur übergeben Sie eine Referenz? Ich werde für die Tatsache, dass Java immer noch eine kopierte pass-by-reference-Sprache. Die Tatsache, dass es eine kopierte Referenz nicht ändern, dass die Terminologie. Sowohl die VERWEISE immer noch auf das gleiche Objekt zeigen. Dies ist ein puristisches argument...
Ich denke Java entwickelt, mit Zeiger in Verstand. Ansonsten, warum
NullPointerException
existiert? Dennoch, für diese wunderbare explanantion, erste Zeiger wird es nur kompliziertSo fallen in der theoretischen Linie #9
System.out.println(person.getName());
was wird sich zeigen? "Tom" oder "Jerry"? Dies ist die Letzte Sache, die mir helfen, diese Hürde Verwirrung.InformationsquelleAutor
Java immer als Wert übergeben, ohne Ausnahmen, immer.
So, wie es ist, dass jemand überhaupt verwirrt von diesem, und glauben, dass Java pass by reference, oder denken, Sie haben ein Beispiel von Java fungiert als Verweis übergeben? Der entscheidende Punkt ist, dass Java nie bietet direkten Zugriff auf die Werte der Objekte selbst, in alle Umstände. Nur der Zugriff auf Objekte wird durch eine Referenz auf das Objekt. Da in Java Objekte sind immer auf die der Zugriff über eine Referenz, sondern als direkt, ist es üblich, zu sprechen, über Felder und Variablen und Methode Argumente als Objekte, wenn pedantisch Sie sind nur Verweise auf Objekte. Die Verwirrung ergibt sich aus dieser (streng genommen falsch) änderung in der Nomenklatur.
So, beim aufrufen einer Methode
int
,long
usw.), der Wert übergeben wird der tatsächliche Wert von der primitiven (Z. B. 3).Also, wenn Sie
doSomething(foo)
undpublic void doSomething(Foo foo) { .. }
die beiden Foos kopiert haben Referenzen, die auf die gleichen Objekte verweisen.Natürlich, als Wert übergeben Sie eine Referenz zu einem Objekt sehr ähnlich sieht (und nicht in der Praxis) die übergabe eines Objekts als Referenz.
Genau. Für alles, was Sie sagen kann über beobachtbare JVM-Verhalten, primitives sein könnte, wird durch Verweis übergeben und konnte live auf dem heap. Sie nicht, aber das ist nicht wirklich beobachten in keiner Weise.
primitive sind unveränderlich? ist, dass neu in Java 7?
unveränderlich sind?". Der Punkt ist, dass Sie können behaupten, dass 'primitive' sind eigentlich (veränderlich) Referenzen, um unveränderliche Objekte.
Zeiger sind unveränderliche, primitive im Allgemeinen sind veränderlich. String ist auch nicht ein primitiver, es ist ein Objekt. Darüber hinaus wird die zugrunde liegende Struktur der String ist ein veränderliches array. Die einzige unveränderliche Sache ist, ist die Länge gut ist, dass die inhärente Natur des arrays.
InformationsquelleAutor
Java Verweise von Wert.
Also Sie können nicht ändern die Referenz, die übergeben bekommt.
Ich habe nie gesagt, "du kannst nicht ändern Sie den Wert der Objekte, die übergeben Argumente". Ich werde sagen, "Sie können nicht ändern Sie den Wert der übergebenen Objektreferenz als Methode argument", das ist eine wahre Aussage über die Java-Sprache. Natürlich können Sie mit ändern Sie den Zustand des Objekts (solange es nicht unveränderlich).
Beachten Sie, dass Sie nicht tatsächlich übergeben von Objekten in java; die Objekte bleiben auf dem heap. Zeiger, um die Objekte übergeben werden können (die kopiert wird, auf den stack-frame der aufgerufenen Methode). Damit Sie sich nie ändern Sie den übergebenen Wert (der Zeiger), aber du bist frei, ihm zu Folgen, und ändern Sie das Ding auf den Haufen, auf die es verweist. Das ist pass-by-value.
Klingt wie Sie nur übergeben Sie eine Referenz? Ich werde für die Tatsache, dass Java immer noch eine kopierte pass-by-reference-Sprache. Die Tatsache, dass es eine kopierte Referenz nicht ändern, dass die Terminologie. Sowohl die VERWEISE immer noch auf das gleiche Objekt zeigen. Dies ist ein puristisches argument...
Java funktioniert nicht ein Objekt übergeben, übergibt es den Wert des Zeigers auf das Objekt. Erzeugt einen neuen Zeiger auf die Speicheradresse des ursprünglichen Objekts in eine neue variable. Wenn Sie den Wert ändern (die Speicher-Adresse zeigt es auf) dieser Zeiger-Variablen in einer Methode, dann wird der ursprüngliche Zeiger in die Methode Aufrufer bleibt unverändert. Wenn Sie den Aufruf der parameter eine Referenz, dann die Tatsache, dass es ein kopieren der original-Referenz, nicht die original-Referenz selbst, so dass es nun zwei Referenzen auf das Objekt bedeutet, dass es ist pass-by-value
InformationsquelleAutor
Fühle ich mich wie das argumentieren über "pass-by-reference-vs pass-by-value" ist nicht das super-hilfreich.
Wenn Sie sagen, "Java ist pass-by-was auch immer (Referenz/Wert)", in beiden Fällen, sind Sie nicht bieten eine vollständige Antwort. Hier ein paar zusätzliche Informationen, die hoffentlich Hilfe zu verstehen, was passiert im Speicher.
Crash-Kurs auf stack/heap bevor wir zu den Java-Implementierung:
Werte gehen auf und aus dem Stapel, in einem schönen, geordneten Weise, wie ein Stapel Teller in einer Mensa.
Speicher im heap (auch bekannt als dynamische Speicher) ist planlos und unorganisiert. Die JVM nur Platz findet, wo immer er kann, und schafft es, als die Variablen, die es verwenden, sind nicht mehr erforderlich.
Okay. First off, lokale stammfunktionen gehen auf den Stapel. Also dieser code:
Ergebnisse, in:
Beim deklarieren und instanziieren eines Objekts. Das eigentliche Objekt geht auf den Haufen. Was geht auf den stack? Die Adresse des Objekts auf dem heap. C++ - Programmierer nennen würde dies ein pointer, aber manche Java-Entwickler sind gegen das Wort "Zeiger". Was auch immer. Weiß nur, dass die Adresse des Objekts geht auf den stack.
Etwa so:
Ein array ist ein Objekt, es geht also auf dem heap sowie. Und was über die Objekte im array? Sie erhalten Ihre eigenen heap-Speicher, und die Adresse jedes Objekts wird in das array.
So, was wird übergeben wenn Sie eine Methode aufrufen? Wenn Sie in ein Objekt, was Sie tatsächlich übergeben wird die Adresse des Objekts. Manche mögen sagen, dass der "Wert" der Adresse, und einige sagen, es ist nur ein Verweis auf das Objekt. Diese ist die genesis des Heiligen Krieges zwischen "Referenz" und "Wert" - Befürworter. Was Sie es nennen ist nicht so wichtig, als dass Sie verstehen, welche übergeben wird, wird die Adresse des Objekts.
Einen String erzeugt wird, und Platz für Sie ist reserviert im heap, und die Adresse der Zeichenkette wird auf dem stack gespeichert werden und angesichts der Kennung
hisName
, da die Adresse des zweiten Strings ist der gleiche wie der erste, wird kein neuer String erstellt wird und keine neuen heap-Speicher reserviert wird, aber eine neue Kennung wird auf dem Stapel erzeugt. Dann nennen wirshout()
: ein neuer stack-frame angelegt und einen neuen Bezeichner, dername
erstellt und zugewiesen die Adresse des bereits vorhandenen Zeichenfolge.So, Wert, Referenz? Sie sagen "Kartoffel".
Menschen sind nicht "tanzen um das eigentliche Thema" der stack vs heap, denn das ist nicht das wirkliche Problem. Es ist eine Implementierung detail, am besten und geradezu falsch im schlimmsten Fall. (Es ist durchaus möglich, Objekte zu Leben, auf dem stack; google "escape-Analyse". Und eine große Anzahl von Objekten enthalten, primitive, wahrscheinlich nicht live auf dem Stapel.) Das eigentliche Problem ist genau der Unterschied zwischen Referenz-Typen und Wert-Typen -- insbesondere, dass der Wert eines Referenz-Typ-variable ist eine Referenz, nicht das Objekt, das es bezeichnet.
Es ist ein "detail", dass Java noch nie benötigt, um tatsächlich zeigen Sie, wo sich ein Objekt lebt in der Erinnerung, und in der Tat scheint entschlossen zu vermeiden undicht, info. Es könnte das Objekt auf dem stack, und Sie würden nie wissen. Wenn Sie sich sorgen, man konzentriert sich auf die falsche Sache-und in diesem Fall, das heißt, ignoriert das eigentliche Problem.
Und so oder so, "primitive" gehen auf den stack" ist falsch. Primitive lokale Variablen, gehen auf den Stapel. (Wenn Sie noch nicht optimiert wurde entfernt, natürlich.) Aber dann, , damit die lokalen Referenzvariablen. Und primitiven Mitglieder definiert, die in einem Objekt Leben, wo das Objekt lebt.
Stimme mit den Kommentaren hier. Stack/heap ist eine Nebensache und nicht relevant. Einige Variablen werden auf dem stack, einige sind in den statischen Speicher (statische Variablen), und viele Leben auf dem heap (alle Objekt-member-Variablen). KEINE dieser Variablen können als Referenz übergeben werden: von einer aufgerufenen Methode es ist NIE möglich, ändern Sie den Wert einer variable, die als argument übergeben. Daher gibt es keine pass-by-reference in Java.
InformationsquelleAutor
Nur um zu zeigen, den Kontrast, vergleichen Sie die folgenden C++ und Java snippets:
In C++: Hinweis: Schlechte code - memory leaks! Aber es zeigt den Punkt.
In Java,
Java hat nur die zwei Arten der übergabe: von Wert für built-in Typen, und durch den Wert des Zeigers für die Objekt-Typen.
Dog **objPtrPtr
zum Beispiel C++, so können wir ändern, was der "Zeiger " Punkte".Dies ist eine der besten Antworten, die ich bisher gesehen habe. Es meist vermeidet die Semantik irrelevant argument der "reference vs-Wert der Referenz" präsentieren anderswo und statt dessen beschreibt die mechanik von dem, was tatsächlich passiert. Ich hatte zu geben, die meisten anderen "pass-by-value" Antworten -1 wegen Ihres selbst-widersprüchlich oder sachlich falschen Inhalten, aber dadurch bekommt man noch +1 statt.
Das bedeutet aber nicht, Antwort für die gegebene Frage in Java. Als die Angelegenheit von der Tat, alles, was in der Java-Methode als Wert Übergeben, nichts mehr.
Diese Beispiele beweisen einfach, dass java die Nutzung der entspricht, die Zeiger in C nicht ? Wo pass-by-value in C sind im Grunde nur Lesen ? Am Ende, dieser ganze thread ist unverständlich
InformationsquelleAutor
Java übergibt Referenzen auf Objekte von Wert.
InformationsquelleAutor
Grundsätzlich ist eine Neuzuweisung der Objekt-Parameter wirkt sich nicht auf das argument ein, z.B.,
ausgedruckt
"Hah!"
stattnull
. Der Grund, warum dies funktioniert, ist, weilbar
ist eine Kopie des Werts, derbaz
, das ist nur ein Verweis auf"Hah!"
. Wenn es die eigentliche Referenz selbst, dannfoo
würde neu definiert habenbaz
zunull
.nicht gibt es einen leichten Unterschied zwischen String-Klasse und alle anderen Klassen ?
InformationsquelleAutor
Ich kann nicht glauben, dass niemand erwähnt Barbara Liskov noch. Wenn Sie selbst entworfen CLU im Jahr 1974 lief Sie in die gleiche Terminologie-problem, und Sie erfand den Begriff call-by-sharing (auch bekannt als call-by-object-sharing und call-by-object -) für diesen speziellen Fall von "call-by-value, wobei der Wert eine Referenz".
Ich glaube wirklich nicht, brauchten wir einen zusätzlichen Begriff - es ist einfach, pass-by-value für einen bestimmten Typ von Wert. Wäre das hinzufügen von "call-by-primitive" hinzufügen Klärung?
Call-by-Sharing
So kann ich-pass-by-reference durch den Austausch von ein paar globalen Kontext-Objekt, oder gar die übergabe eines Kontext-Objekt, das enthält noch andere Referenzen? Ich immer noch pass-by-value, aber zumindest habe ich Zugriff auf Referenzen, die ich kann "ändern" und machen Sie Sie auf etwas anderes zeigen.
InformationsquelleAutor
Die Krux an der Sache ist, dass das Wort Referenz in dem Ausdruck "pass by reference" bedeutet etwas völlig anderes als die übliche Bedeutung des Wortes Referenz in Java.
In der Regel in Java Referenz bedeutet eine Referenz auf ein Objekt. Aber die technischen Bedingungen pass by reference/value von Programmiersprache-Theorie sprechen Verweis auf die Speicherzelle hält die variable, was etwas ganz anderes ist.
Was ist dann eine "NullPointerException"?
Ein leider den Namen Ausnahme von vor Java ließ sich auf eine klare Terminologie. Die semantisch äquivalent Ausnahme in c# heißt NullReferenceException.
Es schien mir immer, dass die Nutzung von "Referenz" in Java-Terminologie ist eine Beeinträchtigung, behindert das Verständnis.
Ich habe gelernt, zu rufen diese sogenannten "Zeiger auf Objekte" als ein "handle auf das Objekt". Dies reduziert Mehrdeutigkeit.
InformationsquelleAutor
In java alles ist Referenz, so dass, wenn Sie so etwas wie:
Point pnt1 = new Point(0,0);
Java funktioniert Folgendes:Referenz. So können wir sagen, dass in Java Bearbeitung von Objekt-durch seine Referenz.
Java nicht pass-Methode Argumente by reference; es gibt Sie von Wert. Ich werde z.B. von diese Website:
Flow des Programms:
Erstellen zwei verschiedene Point-Objekt mit zwei verschiedenen Referenz verbunden.
Als erwartete Ausgabe:
Auf dieser Linie "pass-by-value' geht in das Spiel...
Referenzen
pnt1
undpnt2
sind durch Wert übergeben, um den tricky Methode, was bedeutet, dass Ihnen jetzt auch Verweisepnt1
undpnt2
haben Ihrecopies
namensarg1
undarg2
.Sopnt1
undarg1
Punkte auf das gleiche Objekt. (Gleich für diepnt2
undarg2
)In der
tricky
Methode:In der nächsten
tricky
MethodeHier erstellen Sie zunächst neue
temp
Punkt Referenz Punkt am gleichen Ort wiearg1
Referenz. Dann bewegen Sie sich Referenzarg1
zu Punkt an der gleichen Stelle wiearg2
Referenz.Schließlich
arg2
wird Punkt an der gleichen Stelle wietemp
.Ab hier Rahmen
tricky
Methode ist gegangen, und Sie haben keinen Zugang mehr zu den Referenzen:arg1
,arg2
,temp
. Aber wichtiger Hinweis ist, dass alles, was Sie tun, mit diesen hinweisen, wenn Sie 'im Leben' wird permanent auf Objekt, auf dem Sie Punkt.Also nach der Ausführung der Methode
tricky
, wenn Sie zurück nachmain
haben Sie diese situation:So, jetzt, komplett Ausführung des Programms werden sein:
Ich bin in der Lage zu drucken getauscht-Wert in der main-Methode. in trickey Methode , fügen Sie die folgende Anweisung
arg1.x = 1; arg1.y = 1; arg2.x = 2; arg2.y = 2;
so, als arg1 nun im Besitz der pnt2 refrence und arg2 holding jetzt pnt1-Referenz, also der DruckX1: 2 Y1: 2 X2: 1 Y2: 1
InformationsquelleAutor
Java immer als Wert übergeben werden, nicht als Verweis übergeben
Zunächst müssen wir verstehen, was die wertübergabe und die referenzübergabe sind.
Pass-by-value bedeutet, dass Sie eine Kopie im Speicher der aktuellen parameter den Wert, der übergeben wird. Dies ist eine Kopie des Inhalts des aktuellen Parameters.
Pass by reference (auch als pass by address) bedeutet, dass eine Kopie der Adresse des aktuellen Parameters gespeichert ist.
Manchmal Java geben kann, die illusion von pass-by-reference. Mal sehen, wie es arbeitet, indem Sie das Beispiel unten:
Die Ausgabe dieses Programms ist:
Lassen Sie uns zu verstehen, Schritt für Schritt:
Wie wir alle wissen, es wird ein Objekt im heap und Rückgabe der Referenz-Wert zurück zu t ist. Angenommen, der Wert von t ist
0x100234
(wir wissen nicht, die eigentliche JVM-internen Wert, dies ist nur ein Beispiel) .Beim übergeben der Referenz t um die Funktion wird nicht direkt übergeben, die eigentliche Referenz, Wert von Objekt zu testen, aber es wird das erstellen einer Kopie von t und dann übergeben es an die Funktion. Da ist es Wert übergeben werden,, es übergibt eine Kopie der Variablen, anstatt die eigentliche Referenz. Da sagten wir den Wert von t wurde
0x100234
, t und f haben den gleichen Wert und daher werden Sie auf das gleiche Objekt zeigen.Wenn Sie etwas ändern in die Funktion mit Referenz f es wird ändern Sie den vorhandenen Inhalt des Objekts. Das ist, warum wir haben die Ausgabe
changevalue
, die aktualisiert wird, in der Funktion.Verstehen dies noch deutlicher, betrachten Sie das folgende Beispiel:
Wird dieser Wurf ein
NullPointerException
? Nein, denn es gibt nur eine Kopie der Referenz.Bei der übergabe by reference, es hätte geworfen ein
NullPointerException
, wie unten gesehen:Hoffentlich helfen.
InformationsquelleAutor
Eine Referenz ist immer ein Wert, wenn dargestellt wird, egal welche Sprache Sie verwenden.
Immer eine außerhalb der box anzeigen, lassen sich an der Montage oder einige low-level memory management. Bei den CPU-Ebene eine Referenz, um alles sofort zu einem Wert, wenn es wird in den Speicher geschrieben oder zu einem der CPU-Register. (Das ist der Grund, warum Zeiger ist eine gute definition. Es ist ein Wert, der ein Ziel hat in der gleichen Zeit).
Daten im Speicher hat eine Lage und an dieser Stelle gibt es einen Wert (byte,word, was auch immer). In der Montage haben wir eine komfortable Lösung zu geben, ein Namen bestimmten Lage (auch variable), aber beim kompilieren des Codes, der assembler ersetzt einfach Namen mit der angegebenen Position genau wie Sie Ihren browser ersetzt Domänennamen mit IP-Adressen.
Bis in den Kern ist es technisch unmöglich ist, übergeben Sie einen Verweis auf etwas in jeder Sprache, ohne Vertretung (wenn es sofort zu einem Wert).
Können sagen, wir haben eine variable Foo, seine Lage ist an der 47th byte im Speicher und seine Wert ist 5. Wir haben eine andere variable Ref2Foo, die bei 223rd byte im Speicher, und sein Wert wird 47. Diese Ref2Foo könnte eine technische variable, die nicht explizit vom Programm erstellt. Wenn Sie nur Blick auf 5 und 47 ohne weitere Informationen, sehen Sie nur zwei Werte.
Wenn Sie verwenden Sie als Referenz dann zu erreichen, um
5
wir müssen Reisen:Dies ist, wie Sprung-Tabellen arbeiten.
Wenn wir wollen, dass das aufrufen einer Methode/Funktion/Prozedur mit Foo ' s Wert, es gibt ein paar mögliche Methode zum übergeben der variable an die Methode abhängig von der Sprache und seine diversen Methode invocation-Modi:
In allen Fällen über einem Wert - eine kopieren von einem vorhandenen Wert - erstellt wurde, ist es jetzt bis zu den empfangenden Methode, damit umzugehen. Wenn Sie schreiben "Foo" innerhalb der Methode, entweder es wird gelesen aus EAX, oder automatisch aufgelöst, oder doppelklicken aufgelöst, der Prozess hängt davon ab, wie die Sprache funktioniert und/oder was der Typ von Foo diktiert. Dies ist vor dem Entwickler verborgen, bis Sie umgeht die Dereferenzierung Prozess. So ein Referenz ist ein Wert wenn vertreten, weil eine Referenz ist ein Wert, der bearbeitet werden (Sprache, level).
Nun haben wir bestanden Foo die Methode:
Foo = 9
) es betrifft nur den lokalen Bereich, wie Sie eine Kopie des Wertes. Von innen die Methode, die wir nicht selbst bestimmen, wo im Speicher die original-Foo, gefunden werden.Foo = 11
), es könnte sich ändern, Foo Global (abhängig von der Sprache, dh. Java oder Pascal istprocedure findMin(x, y, z: integer;
var m: integer);
). Allerdings, wenn die Sprache erlaubt die Umgehung der dereference-Prozess, können Sie ändern47
, sagen49
. An diesem Punkt Foo zu haben scheint verändert worden, wenn Sie es Lesen, weil Sie Sie geändert haben, die lokalen Zeiger. Und wenn Sie waren, dies zu ändern Foo innerhalb der Methode (Foo = 12
), werden Sie wahrscheinlich FUBAR die Ausführung des Programms (aka. segfault), da schreiben Sie zu einem anderen Speicher als erwartet, können Sie sogar ändern Sie ein Gebiet, das dazu bestimmt ist, zu halten, ausführbare Datei Programm und das schreiben, um es zu ändern ausführen von code (Foo ist jetzt nicht bei47
). ABER Foo, die den Wert von47
nicht ändern, weltweit, nur das man innerhalb der Methode, weil47
war auch eine Kopie der Methode.223
innerhalb der Methode schafft es das gleiche Chaos wie in 3. oder 4. (ein Zeiger, der auf einen jetzt schlechter Wert, das ist wieder als ein Zeiger), aber dies ist immer noch ein lokales problem, 223 war kopiert. Allerdings, wenn Sie sind in der Lage zu dereferenzierenRef2Foo
(223
), zu erreichen und zu ändern, die darauf Wert47
sagen, zu49
wird es sich auf Foo Global, weil in diesem Fall die Methoden bekam eine Kopie von223
aber auf die verwiesen wird47
nur einmal vorhanden, und die änderung, die zu49
führen wird jedesRef2Foo
Doppel-Dereferenzierung zu einem falschen Wert.Erbsenzählerei auf unbedeutende details, sogar Sprachen, die pass-by-reference übergeben Werte an Funktionen, aber diese Funktionen wissen, dass Sie haben, um es für die Dereferenzierung Zwecke. Dieser pass-die-Referenz-als-Wert ist nur vom Programmierer verborgen, denn es ist praktisch nutzlos, und die Terminologie ist nur pass-by-reference.
Strengen pass-by-value ist auch sinnlos, es würde bedeuten, dass ein 100-Mbyte-array soll kopiert werden jedes mal, wenn wir eine Methode aufrufen mit dem array als argument, daher Java nicht grundsätzlich pass-by-value. Jede Sprache würde übergeben Sie einen Verweis auf diese riesige Zahl (als value) und entweder beschäftigt copy-on-write-Mechanismus, wenn das array kann geändert werden, lokal innerhalb der Methode oder ermöglicht die Methode (wie Java funktioniert) so ändern Sie das array Global (von der Anrufer-Ansicht) und ein paar Sprachen ermöglicht das ändern des Werts der Referenz selbst.
So, in kurz-und in der Java-eigenen Terminologie Java ist pass-by-value wo Wert werden kann: entweder eine realen Wert oder eine Wert , ist die Darstellung eines Referenz.
...der entscheidende Punkt ist, dass der Empfänger der Objekt-id, identifiziert das array speichern kann, die Objekt-id, wohin es will, und gebe Sie, wem er will, und jeder Empfänger Zugriff auf oder ändern Sie das array, wenn es will. Im Gegensatz dazu, wenn ein array per Referenz übergeben in einer Sprache wie Pascal, die unterstützt solche Dinge, die aufgerufene Methode konnte tun, was es wollte mit dem array, aber konnte nicht speichern Sie die Referenz in einer Weise zu erlauben, code zu ändern, array, nachdem es zurückgegeben.
In der Tat, in der Pascal-man kann erhalten Sie die Adresse jeder variable, sei es vergangen-by-reference oder lokal kopiert,
addr
tut es nicht typisiert,@
tut es mit, und Sie können ändern Sie die referenzierte variable später (außer lokal kopiert). Aber ich sehe nicht den Punkt, warum Sie das tun würden. Das Stück Papier in deinem Beispiel (Objekt #24601) ist ein Verweis,dessen Zweck ist zu helfen, finden Sie das array im Speicher, es enthält keine array-Daten in sich. Wenn Sie starten Sie Ihr Programm, das dasselbe array kann ein anderes Objekt-id auch wenn Ihr Inhalt wird der gleiche sein wie in der vorherigen Ausführung.Ich hatte gedacht, dass der " @ " - operator wurde nicht Teil von standard-Pascal, aber umgesetzt wurde als Allgemeine Erweiterung. Ist es Teil der standard? Mein Punkt war, dass in einer Sprache mit echter pass-by-ref, und nicht die Fähigkeit zum konstruieren eines nicht-Ephemere Zeiger auf ein kurzlebiges Objekt, das code enthält nur die Referenz auf ein array, überall im Universum, bevor Sie das array als Referenz kann wissen, es sei denn, der Empfänger "cheats" es wird immer noch die einzige Referenz hinterher. Der einzig sichere Weg, um zu erreichen, dass in Java wäre zu bauen ein temporäres Objekt...
...die kapselt eine
AtomicReference
und weder macht die Referenz noch sein Ziel, sondern beinhaltet Methoden, Dinge zu tun, um das Ziel, einmal den code, an die das Objekt übergeben wurde, gibt dieAtomicReference
[zu dem sein Schöpfer hielt eine direkte Referenz], werden für ungültig erklärt und aufgegeben. Das wäre die richtige Semantik, aber es wäre langsam und eklig.InformationsquelleAutor
Java ist call-by-value
Wie es funktioniert
Du immer übergeben Sie eine Kopie der bits der Wert der Referenz!
Wenn es ein primitiver Datentyp diese bits enthalten den Wert des primitiven Datentyps selbst, Das ist, warum, wenn wir den Wert ändern, der header innerhalb der Methode, dann sind es nicht die änderungen außerhalb.
Wenn es ein Objekt-Datentyp, wie Foo foo=new Foo() dann in diesem Fall kopieren Sie die Adresse des Objekts übergibt, wie eine Datei-Verknüpfung , angenommen wir haben eine Textdatei abc.txt bei C:\desktop und nehmen wir an, wir machen Verknüpfung von der Datei und setzen diese in C:\desktop\abc-shortcut also, wenn Sie den Zugriff auf die Datei von C:\desktop\abc.txt und schreiben 'Stack-Überlauf' und die Datei schließen und erneut öffnen Sie die Datei von shortcut-dann schreiben Sie ' ist die größte online-community für Programmierer lernen " so wird die gesamte Datei ändern, werden 'Stack-Überlauf ist die größte online-community für Programmierer lernen" das heißt, es spielt keine Rolle, von wo aus Sie die Datei öffnen , jedes mal waren wir auf dieselbe Datei zugreifen können , hier können wir davon ausgehen Foo als Datei und nehme foo gespeichert 123hd7h(original-Adresse wie C:\desktop\abc.txt ) Adresse und 234jdid(kopierte Adresse wie C:\desktop\abc-shortcut, die tatsächlich enthält die original-Adresse der Datei drin) ..
So für besseres Verständnis machen shortcut Datei und fühlen...
InformationsquelleAutor
Soweit ich weiß, Java kennt nur call-by-value. Dies bedeutet für primitive Datentypen arbeiten Sie mit einer Kopie und für die Objekte, die Sie arbeiten mit einer Kopie der Referenz auf die Objekte. Aber ich denke, es gibt einige Fallstricke; zum Beispiel, dies wird nicht funktionieren:
So füllen Hallo Welt und nicht-Welt Hallo, weil in der swap-Funktion, die Sie verwenden Exemplaren, die keine Auswirkungen auf die Verweise in der Hauptsache. Aber wenn Sie Ihre Objekte sind nicht unveränderlich, Sie können es ändern, zum Beispiel:
So füllen Hello World " auf der Kommandozeile. Wenn Sie ändern StringBuffer in String-es wird produzieren nur Hallo, weil String immutable. Zum Beispiel:
Aber könnten Sie machen einen wrapper für String wie diesen, die Sie verwenden können, um mit Strings:
edit: ich glaube, das ist auch der Grund für die Verwendung von StringBuffer, wenn es um "hinzufügen" zwei Strings, da kann man modifie das original-Objekt, das u kann nicht mit unveränderlichen Objekten wie String ist.
swap(a, b)
dass (1) swapsa
undb
aus der Anrufer-POV, (2) der Typ ist gebunden, soweit die statische Typisierung ermöglicht (was bedeutet, es mit mit einem anderen Typ erfordert nichts mehr als eine änderung des deklarierten Typen dera
undb
), und (3) nicht erforderlich, die der Anrufer explizit einen Zeiger übergeben oder Namen, dann wird die Sprache unterstützt durch Verweis übergeben wird."..für primitive Datentypen arbeiten Sie mit einer Kopie und für die Objekte, die Sie arbeiten mit einer Kopie der Referenz auf die Objekte" - perfekt geschrieben!
InformationsquelleAutor
Nein, es ist nicht pass-by-reference.
Java ist pass-by-value gemäß der Java Language Specification:
InformationsquelleAutor
Lassen Sie mich versuchen zu erklären mein Verständnis mit Hilfe von vier Beispielen. Java ist pass-by-value und nicht pass-by-reference
/**
Wert Übergeben
In Java werden alle Parameter als Wert übergeben, D. H. die Zuordnung eines Arguments einer Methode ist nicht für den Aufrufer sichtbar.
*/
Beispiel 1:
Ergebnis
Beispiel 2:
/**
*
* Pass-By-Value
*
*/
Ergebnis
Beispiel 3:
/**
Diese "Pass-By-Value hat ein Gefühl von "Pass By Reference'
Einige Leute sagen, primitive Typen und 'String' sind 'pass per value'
und Objekte sind "pass by reference'.
Aber aus diesem Beispiel können wir verstehen, dass es infact pass-by-value nur,
wenn man bedenkt, dass hier übergeben wir die Referenz als Wert.
ie: Referenz wird als Wert übergeben.
Das ist, warum sind in der Lage, sich zu verändern und dennoch bewahrheitet es sich nach den lokalen Bereich.
Aber wir können nicht ändern, die eigentliche Referenz außerhalb des ursprünglichen Umfang.
was das bedeutet, demonstriert das nächste Beispiel PassByValueObjectCase2.
*/
Ergebnis
Beispiel 4:
/**
Zusätzlich zu dem, was erwähnt wurde, in Example3 (PassByValueObjectCase1.java), wir können nicht ändern, die eigentliche Referenz außerhalb des ursprünglichen Umfang."
Hinweis: ich bin nicht einfügen den code für
private class Student
. Die definition der Klasse fürStudent
ist die gleiche wie Example3.*/
Ergebnis
InformationsquelleAutor
Kann man nie referenzübergabe in Java, und einer der Wege, die offensichtlich ist, wenn Sie zurückkehren möchten, mehr als einen Wert von einem Aufruf der Methode. Betrachten Sie die folgende Stück code, der in C++:
Manchmal wollen Sie das gleiche Muster verwenden, die in Java, aber Sie können es nicht; zumindest nicht direkt. Stattdessen könnte man etwas wie das hier tun:
Wie schon erläutert, die in früheren Antworten, die in Java-sind Sie übergeben einen Zeiger auf das array als einen Wert in
getValues
. Das ist genug, denn die Methode ändert dann die array-Elements, und von der Konvention, Sie erwarten eine element 0 enthalten, ist der Rückgabewert. Natürlich können Sie tun dies in anderer Weise, wie strukturieren Sie Ihren code so, das ist nicht nötig, oder konstruieren eine Klasse enthält den Rückgabewert oder lassen Sie es festgelegt werden. Aber die einfachen Muster, die Sie in C++ ist nicht verfügbar in Java.InformationsquelleAutor
Ich dachte, ich würde tragen Sie diese Antwort, um mehr details aus der Leistungsbeschreibung.
Erste, Was ist der Unterschied zwischen der übergabe by reference vs. Wert übergeben?
Oder von wikipedia, zum Thema pass-by-reference
Und zum Thema pass-by-value
Zweitens müssen wir wissen, was Java verwendet in seiner Methode aufrufen. Die Java Language Specification Staaten
So weist er (bzw. bindet) der Wert des Arguments, um die entsprechenden parameter-variable.
Was ist der Wert des Arguments?
Wir betrachten die Referenz-Typen, die Java Virtual Machine Specification Staaten
Den Java Language Specification auch Staaten
Den Wert eines Arguments (von einigen Referenz-Typ) ist ein Zeiger auf ein Objekt. Beachten Sie, dass eine variable, ein Aufruf einer Methode mit einem Referenztyp return-Typ, und eine instance creation expression (
new ...
) alle lösen um einen Typ der Referenz-Wert.So
alle binden den Wert einer Referenz auf einen
String
Instanz der Methode neu angelegt, - parameter,param
. Das ist genau das, was die definition von pass-by-value beschrieben. Als solche, Java ist pass-by-value.Die Tatsache, dass Sie können Sie die Referenz zum aufrufen einer Methode oder den Zugriff auf ein Feld des referenzierten Objekts ist völlig irrelevant für das Gespräch. Die definition von pass-by-reference wurde
In Java, ändern der Variablen zugewiesen wird. In Java, wenn Sie zugewiesen die Variablen innerhalb der Methode, es würde unbemerkt an den Aufrufer. Geändert wird, referenziert das Objekt durch die variable ist ein anderes Konzept völlig.
Primitive Werte sind definiert in the Java Virtual Machine Specification, hier. Der Wert der type ist das entsprechende integral-oder floating-point-Wert, codiert entsprechend (8, 16, 32, 64, etc. bits).
InformationsquelleAutor
Den Unterschied, oder vielleicht nur die Art und Weise ich erinnere mich, wie ich benutzt, um unter den gleichen Eindruck wie der original-poster ist: Java wird immer durch Wert übergeben. Alle Objekte( in Java, für alles, außer für primitive Typen) in Java sind Referenzen. Diese Referenzen als Wert übergeben werden.
InformationsquelleAutor
Wie viele Menschen erwähnt, Java ist immer pass-by-value
Hier ist ein weiteres Beispiel, das Ihnen helfen wird, die Differenz (der klassische swap-Beispiel):
Drucke:
Dies geschieht, weil iA und iB werden neue lokale Referenz-Variablen, die den gleichen Wert des übergebenen Referenzen (Sie Punkt a und b, respektive). So, versuchen, ändern Sie die Referenzen iA oder iB wird nur die änderung im lokalen Bereich und nicht außerhalb von dieser Methode.
InformationsquelleAutor
Java hat nur durch Wert übergeben. Ein sehr einfaches Beispiel, dies zu überprüfen.
obj
(null
) verabschiedetinit
, nicht eine Referenz aufobj
.InformationsquelleAutor
In Java nur Referenzen übergeben werden und die als Wert übergeben werden:
Java Argumente sind alle durch Wert übergeben (die Referenz kopiert wird, wenn von der-Methode) :
Im Fall von primitiven Datentypen, Java Verhalten ist einfach:
Der Wert wird kopiert in eine andere Instanz des primitiven Typs.
Im Falle von Objekten, dies ist der gleiche:
Objekt-Variablen sind Zeiger (- Eimer) halten nur Objekt Adresse, die erstellt wurde, mit dem Schlüsselwort "new", und kopiert werden wie primitive Typen.
Das Verhalten kann anders Aussehen, von primitiven Typen:, Weil das kopierte Objekt-variable enthält die gleiche Adresse (auf dasselbe Objekt)
Objekt Inhalt/Mitglieder könnte noch geändert werden, die innerhalb einer Methode und den späteren Zugriff außerhalb, geben die illusion, dass das (mit -) Objekt selbst wurde durch einen Verweis übergeben.
"String" Objekte zu sein scheinen, eine perfekte gegen-Beispiel zu der urbanen Legende, die besagt, dass "Objekte werden by reference übergeben":
In der Wirkung, innerhalb einer Methode werden Sie nie in der Lage sein, um den Wert zu aktualisieren, der einen String als argument übergeben wird:
Einem String-Objekt, enthält Zeichen, die durch ein array deklariert letzten, die nicht geändert werden können.
Nur die Adresse des Objekts kann durch ein anderes ersetzt werden "neu".
Mit "neu", um Aktualisierung der variable wird nicht lassen Sie das Objekt von außen zugreifbar sein, da die variable wurde zunächst durch Wert übergeben und kopiert.
bitte Lesen Sie: - Objekte nicht per Referenz übergeben, das ist ein ledgend: String a=new String("unverändert");
public void changeit(String changeit){changit = "geändert";} changeIt (); assert(a.equals("unverändert"));
Dies ist ein weiteres großartiges Beispiel für den Trugschluss der "es ist nicht vorbei-Referenz" Semantik-argument. Diese Antwort sagt genau in dem kühnen Satz: "nur Referenzen übergeben werden." Entweder eine Referenz übergeben wird, oder ein Verweis ist nicht bestanden. Sie sagten gerade selbst, dass eine Referenz übergeben wird. Mit den Worten "es ist nicht per Referenz übergeben, da eine Referenz übergeben wird aber..." Sie versuchen, einen Punkt zu machen, indem mangeln Englisch.
durch die Referenz" bedeutet nicht "übergeben Sie einen Wert, der ein Mitglied eines Typs, das als 'Referenz' in Java". Die beiden Verwendungen von "Referenz" bedeutet, dass verschiedene Dinge.
InformationsquelleAutor
Ich denke immer, dass es als "pass by copy". Es ist eine Kopie des Werts, sei es primitiv-oder Referenz. Wenn es eine primitiv es ist eine Kopie des bits, das sind die Wert-und wenn es ein Objekt ist eine Kopie der Referenz.
Ausgabe von java PassByCopy:
Primitiven wrapper-Klassen und Strings sind unveränderlich, so dass jedes Beispiel, das mit diesen Arten nicht die gleiche Arbeit wie andere Typen/Objekte.
InformationsquelleAutor
Habe ich einen thread für diese Art Fragen für alle Programmiersprachen hier.
Java ist auch erwähnt. Hier ist die kurze Zusammenfassung:
Objekt die Verweise zeigen auf
die ursprünglichen Objekte. (wenn das
Methode selbst verändert einige Werte)
InformationsquelleAutor
Ein paar Korrekturen zu einigen Beiträgen.
C NICHT unterstützt pass-by-reference. Es ist IMMER durch Wert übergeben. C++ unterstützt pass by reference ist aber nicht der Standard und ist sehr gefährlich.
Ist es egal, was der Wert ist in Java: primitive oder Adresse(in etwa) des Objektes, es ist IMMER durch Wert übergeben.
Wenn ein Java-Objekt "verhält", wie es ist, wird durch Verweis übergeben, dass ist eine Eigenschaft der Veränderlichkeit und absolut nichts zu tun hat mit passing-Mechanismen.
Ich bin nicht sicher, warum dies ist so verwirrend, vielleicht, weil so viele Java - "Programmierer" nicht formal ausgebildet, und somit nicht verstehen, was wirklich Los ist in Erinnerung?
Yeah, in C Sie erstellen können Zeiger nicht nur auf Objekte, sondern auf beliebige Variablen - so können Sie ganz einfach simulieren "call-by-reference" an eine variable. In Java funktioniert dies nur für Variablen, die durch einen umlaufenden Objekt, das Sie geben können.
InformationsquelleAutor
Um eine lange Geschichte kurz, Java Objekte haben einige sehr eigenartigen Eigenschaften.
Im Allgemeinen wurde die Java-primitive Typen (
int
,bool
,char
,double
usw.), die direkt übergeben werden, die von Wert. Dann Java-Objekte (alles abgeleitet ausjava.lang.Object
). Objekte sind eigentlich immer gehandhabt, die durch einen Verweis (eine Referenz ein Zeiger, den Sie nicht berühren kann). Das bedeutet, dass im Effekt-Objekte werden per Referenz übergeben, da die Verweise sind in der Regel nicht interessant. Es bedeutet jedoch, dass Sie nicht ändern können, das Objekt wird gezeigt, wie die Referenz selbst durch Wert übergeben wird.Klingt das seltsam und verwirrend? Betrachten wir, wie C implementiert pass by reference und pass-by-value. In C, die Standard-Konvention ist durch Wert übergeben.
void foo(int x)
geht ein int-Wert.void foo(int *x)
ist eine Funktion, die nicht wollen, dass einint a
, sondern ein Zeiger auf ein int:foo(&a)
. Würde man dies mit der&
Betreiber zu übergeben Sie eine variable Adresse.Nehmen Sie diese in C++, und wir haben Referenzen. Referenzen sind im Grunde (in diesem Kontext) syntaktischer Zucker, blenden Sie den Zeiger ein Teil der Gleichung:
void foo(int &x)
genannt wirdfoo(a)
, wo der compiler selbst weiß, dass es eine Referenz ist, und die Adresse der nicht-Referenz -a
übergeben werden sollte. In Java werden alle Variablen mit verweisen auf Objekte sind eigentlich der Typ der Referenz, in der Tat zwingt die call-by-reference für die meisten beabsichtigt und Zwecke ist ohne Feinabstimmung (und Komplexität) gewährt, zum Beispiel C++.InformationsquelleAutor
Java übergibt Parameter by VALUE und by-value NUR.
Um eine lange Geschichte kurz geschnitten:
Es bedeutet, dass Sie nicht ändern können, den Verweis aus dem Objekt selbst, aber Sie können immer ändern Sie die Eigenschaften des Objekts.
Eine Problemumgehung ist die Verwendung
StringBuilder
parameter anstelleString
. Und Sie können immer arrays verwenden!you can't change the reference from the object itself
So ein Objekt kann geändert werden, mithilfe dessen öffentliche Schnittstellen konnte aber nicht sein, ersetzen Sie mit JMD anderes ich.e Ehrerbietung und durch diese java-erzielt beste aus beiden Welten
InformationsquelleAutor