Java Speicherzuweisung auf stack vs heap
Ich fühle mich wie ein Neuling für diese Frage-aber warum ist es so, dass wenn ich den pass der Satz unten in meine Methode und zeigen Sie es auf ein neues HashSet, es kommt immer noch als die EmptySet? Ist es, weil die lokalen Variablen auf dem Stapel reserviert, und so ist meine neue ist wie weggeblasen, wenn ich die Ausfahrt der Methode? Wie könnte ich erreichen das funktionale äquivalent?
import java.util.HashSet;
import java.util.Set;
public class TestMethods {
public static void main(final String[] args) {
final Set<Integer> foo = java.util.Collections.emptySet();
test(foo);
}
public static void test(Set<Integer> mySet) {
mySet = new HashSet<Integer>();
}
}
Du musst angemeldet sein, um einen Kommentar abzugeben.
Java Verweise von Wert, denken Sie an
mySet
als nur eine Kopie desfoo
Referenz. Invoid test(Set<Integer> mySet)
, diemySet
- variable eine lokale variable innerhalb der Funktion, so setzen Sie es um etwas anderes, nicht auf die Anrufer inmain
.mySet
verweist(oder "Punkt", wenn Sie möchten) den gleichen Satz wie diefoo
variable inmain
obwohl.Wenn Sie möchten, ändern Sie die Referenz in den wichtigsten, die Sie tun könnten, z.B.:
Nicht. Es ist, weil der argument-übergabe-Semantik von Java.
Java-Argumente übergeben werden "von Wert", aber in dem Fall ein Objekt oder array-Typ, der Wert, den Sie übergeben das Objekt/array-Referenz. Beim erstellen und zuweisen einer neuen set-Objekt zu
mySet
Sie sind einfach die Einstellung der lokalen Variablen /parameter. Da Java verwendet durch Wert übergeben, hat dies keine Auswirkung auf diefoo
variable in dermain
Methode.Beim betreten der
test
Methode, haben Sie zwei Kopien der Verweis auf dieHashSet
- Instanz erstellt, in diemain
Methode; eine infoo
und eine inmySet
. Dein code ersetzt dann die Referenz inmySet
mit einem Verweis auf eine neu erstellteHashSet
, aber diese neue Referenz nicht an den Aufrufer übergeben. (Sie könnte den code ändern, um es weiterzugeben zurück ... zum Beispiel, wie das Ergebnis dertest
Methode. Aber Sie müssen dies ausdrücklich tun.)Ist, weil, wenn Sie rufen Sie eine Instanz-Methode mit der Referenz in
foo
odermySet
, dass die Methode ausgeführt wird, auf das Objekt (HashSet
), die die Referenz verweist. Unter der Annahme, dass die zwei Referenzen auf das gleiche Objekt zeigen, Ihre "Zuteilung erhalten wird". Oder genauer gesagt, können Sie beobachten, die Auswirkungen von Operationen, die auf der einen Verweis auf ein Objekt über Operationen auf anderen Referenzen auf das gleiche Objekt.Nur daran erinnern, dass die Java-Methode aufruft, kopieren, Referenzen auf Objekt, nicht das Objekt selbst.
Durch die Art und Weise, die Sie nicht in der Lage sein, eigene Elemente zu einem set zurückgegeben
Collections.emptySet()
. Das set-Objekt ist unveränderlich. Der Aufruf von (zum Beispiel)add
auf, wird eine Ausnahme geworfen.Ihre 'foo' bezeichnet eine leere Menge Los in die test () - Aufruf, der Testanruf nicht ändern , dass Objekt, und so ist es immer noch eine leere Menge auf der Rückkehr von dort.
Innerhalb der test () - Methode, 'mySet' ist nur eine lokale Referenz, die sich auf das original-set (foo) auf den Eintrag, und wenn du hast die Zuweisung einer neuen HashSet auf den Verweis, Sie verloren die Referenz auf das original gesetzt. Aber diese Effekte sind alle ganz lokal auf die test () - Methode, weil java einfach gab test() wird eine Kopie der Referenz auf das original gesetzt.
Nun, innerhalb von test(), da Sie eine Referenz auf das ursprüngliche Objekt, Sie kann ändern Sie das Objekt. Zum Beispiel könnten Sie fügen Sie Elemente zu diesem Satz. Aber Sie können nicht ändern Sie den Verweis in die aufrufende Funktion, Sie kann nur verändern, was es sich bezieht. So können Sie nicht ersetzen, die Sammlung mit einem anderen, und wenn Sie wollten, eine HashSet in den ersten Platz, würden Sie haben, um die neue HashSet in main().
Nicht sicher, ob ich die Frage verstehe. In der
test
Methode, die Sie instanziieren Sie ein neues festlegen und die Zuordnung zu den lokalenmySet
variable.mySet
dann nicht mehr auf den gleichen Satz wiefoo
macht zurück inMain
.Zurückkehren, wenn Sie von der Methode " foo " noch verweist auf die ursprüngliche
emptySet()
und dieHashSet
erstellt in der Methode gekennzeichnet werden, die für die garbage collection.Ich bin nicht sicher, ob ich verstehe diese Frage, sind Sie auf der Suche nach einer Rückkehr?
Nun, wenn Sie zuweisen foo, um was zu testen gibt, haben Sie das "funktionale äquivalent"?
sollten Sie dieses Buch Lesen:
"A Programmer' s Guide to Java SCJP Certification: A Comprehensive Primer (3rd Edition)"