Übergibt Java als Referenz oder als Wert?

In vielen Programmiersprachen können Parameter als Referenz oder als Wert übergeben werden . In Java können wir Parameter nur als Wert übergeben . Dies setzt einige Grenzen und wirft auch Fragen auf. Was passiert beispielsweise mit dem Wert nach der Ausführung der Methode, wenn der Parameterwert in der Methode geändert wird? Möglicherweise fragen Sie sich auch, wie Java Objektwerte im Speicherheap verwaltet. Mit diesem Java Challenger können Sie diese und andere häufig gestellte Fragen zu Objektreferenzen in Java lösen.

Holen Sie sich den Quellcode

Holen Sie sich den Code für diesen Java Challenger. Sie können Ihre eigenen Tests ausführen, während Sie den Beispielen folgen.

Objektreferenzen werden als Wert übergeben

Alle Objektreferenzen in Java werden als Wert übergeben. Dies bedeutet, dass eine Kopie des Werts an eine Methode übergeben wird. Der Trick ist jedoch, dass das Übergeben einer Kopie des Werts auch den tatsächlichen Wert des Objekts ändert. Beginnen Sie mit diesem Beispiel, um zu verstehen, warum:

 public class ObjectReferenceExample { public static void main(String... doYourBest) { Simpson simpson = new Simpson(); transformIntoHomer(simpson); System.out.println(simpson.name); } static void transformIntoHomer(Simpson simpson) { simpson.name = "Homer"; } } class Simpson { String name; } 

Was wird Ihrer Meinung simpson.namenach nach der transformIntoHomerAusführung der Methode sein?

In diesem Fall wird es Homer sein! Der Grund dafür ist, dass Java-Objektvariablen lediglich Verweise sind, die auf reale Objekte im Speicherheap verweisen. Obwohl Java Parameter nach Wert an Methoden übergibt, wird daher auch das reale Objekt geändert, wenn die Variable auf eine Objektreferenz verweist.

Wenn Sie sich immer noch nicht ganz sicher sind, wie das funktioniert, sehen Sie sich die folgende Abbildung an.

Rafael Chinelato Del Nero

Werden primitive Typen als Wert übergeben?

Wie Objekttypen werden auch primitive Typen als Wert übergeben. Können Sie im folgenden Codebeispiel ableiten, was mit den primitiven Typen geschehen wird?

 public class PrimitiveByValueExample { public static void main(String... primitiveByValue) { int homerAge = 30; changeHomerAge(homerAge); System.out.println(homerAge); } static void changeHomerAge(int homerAge) { homerAge = 35; } } 

Wenn Sie festgestellt haben, dass sich der Wert auf 30 ändern würde, sind Sie korrekt. Es ist 30, weil Java (wieder) Objektparameter als Wert übergibt. Die Zahl 30 ist nur eine Kopie des Wertes, nicht der tatsächliche Wert. Primitive Typen werden im Stapelspeicher zugewiesen, sodass nur der lokale Wert geändert wird. In diesem Fall gibt es keine Objektreferenz.

Übergeben unveränderlicher Objektreferenzen

Was wäre, wenn wir denselben Test mit einem unveränderlichen StringObjekt durchführen würden?

Das JDK enthält viele unveränderliche Klassen. Beispiele hierfür sind die Wrapper - Typen Integer, Double, Float, Long, Boolean, BigDecimal, und natürlich die sehr bekannte StringKlasse.

Beachten Sie im nächsten Beispiel, was passiert, wenn wir den Wert von a ändern String.

 public class StringValueChange { public static void main(String... doYourBest) { String name = ""; changeToHomer(name); System.out.println(name); } static void changeToHomer(String name) { name = "Homer"; } } 

Was denkst du wird die Ausgabe sein? Wenn Sie "" erraten haben, dann herzlichen Glückwunsch! Dies geschieht, weil ein StringObjekt unveränderlich ist. Dies bedeutet, dass die Felder im Objekt Stringendgültig sind und nicht geändert werden können.

Wenn Stringwir die Klasse unveränderlich machen, haben wir eine bessere Kontrolle über eines der am häufigsten verwendeten Objekte von Java. Wenn der Wert von a Stringgeändert werden könnte, würde dies viele Fehler verursachen. Beachten Sie auch, dass wir kein Attribut der StringKlasse ändern . Stattdessen weisen wir ihm einfach einen neuen StringWert zu. In diesem Fall wird der Wert „Homer“ namein der changeToHomerMethode übergeben. Der String„Homer“ kann nach changeToHomerAbschluss der Ausführung durch die Müllabfuhr gesammelt werden . Obwohl das Objekt nicht geändert werden kann, ist die lokale Variable.

Saiten und mehr

Erfahren Sie mehr über Javas StringKlasse und mehr: Sehen Sie alle Beiträge von Rafael in der Java Challengers-Reihe.

Übergeben veränderbarer Objektreferenzen

Im Gegensatz dazu Stringsind die meisten Objekte im JDK veränderbar, wie die StringBuilderKlasse. Das folgende Beispiel ähnelt dem vorherigen, bietet jedoch StringBuildereher Funktionen als String:

 static class MutableObjectReference { public static void main(String... mutableObjectExample) { StringBuilder name = new StringBuilder("Homer "); addSureName(name); System.out.println(name); } static void addSureName(StringBuilder name) { name.append("Simpson"); } } 

Können Sie die Ausgabe für dieses Beispiel ableiten? In diesem Fall lautet die Ausgabe "Homer Simpson", da wir mit einem veränderlichen Objekt arbeiten. Sie können dasselbe Verhalten von jedem anderen veränderlichen Objekt in Java erwarten.

Sie haben bereits erfahren, dass Java-Variablen als Wert übergeben werden, was bedeutet, dass eine Kopie des Werts übergeben wird. Denken Sie daran, dass der kopierte Wert auf ein reales Objekt im Java-Speicherheap verweist . Durch Übergeben des Werts wird der Wert des realen Objekts weiterhin geändert.

Nehmen Sie die Herausforderung der Objektreferenzen an!

In diesem Java Challenger testen wir, was Sie über Objektreferenzen gelernt haben. Im folgenden Codebeispiel sehen Sie die unveränderliche Stringund die veränderbare StringBuilderKlasse. Jedes wird als Parameter an eine Methode übergeben. Wenn Sie wissen, dass Java nur als Wert übergeben wird, was wird Ihrer Meinung nach die Ausgabe sein, sobald die Hauptmethode dieser Klasse ausgeführt wird?

 public class DragonWarriorReferenceChallenger { public static void main(String... doYourBest) { StringBuilder warriorProfession = new StringBuilder("Dragon "); String warriorWeapon = "Sword "; changeWarriorClass(warriorProfession, warriorWeapon); System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon); } static void changeWarriorClass(StringBuilder warriorProfession, String weapon) { warriorProfession.append("Knight"); weapon = "Dragon " + weapon; weapon = null; warriorProfession = null; } } 

Hier sind die Optionen. Überprüfen Sie am Ende dieses Artikels den Antwortschlüssel.

A : Krieger = null Waffe = null

B : Krieger = Drachenwaffe = Drache

C : Krieger = Drachenritterwaffe = Drachenschwert

D : Krieger = Drachenritterwaffe = Schwert

Was ist gerade passiert?

Der erste Parameter im obigen Beispiel ist die warriorProfessionVariable, bei der es sich um ein veränderbares Objekt handelt. Der zweite Parameter, Waffe, ist unveränderlich String:

 static void changeWarriorClass(StringBuilder warriorProfession, String weapon) { ... } 

Now let’s analyze what is happening inside this method. At the first line of this method, we append the Knight value to the warriorProfession variable. Remember that warriorProfession is a mutable object; therefore the real object will be changed, and the value from it will be “Dragon Knight.”

 warriorProfession.append("Knight"); 

In the second instruction, the immutable local String variable will be changed to “Dragon Sword.” The real object will never be changed, however, since String is immutable and its attributes are final:

 weapon = "Dragon " + weapon; 

Finally, we pass null to the variables here, but not to the objects. The objects will remain the same as long as they are still accessible externally--in this case through the main method. And, although the local variables will be null, nothing will happen to the objects:

 weapon = null; warriorProfession = null; 

From all of this we can conclude that the final values from our mutable StringBuilder and immutable String will be:

 System.out.println("Warrior=" + warriorProfession + " Weapon=" + warriorWeapon); 

The only value that changed in the changeWarriorClass method was warriorProfession, because it’s a mutable StringBuilder object. Note that warriorWeapon did not change because it’s an immutable String object.

The correct output from our Challenger code would be:

D: Warrior=Dragon Knight Weapon=Sword.

Video challenge! Debugging object references in Java

Debugging is one of the easiest ways to fully absorb programming concepts while also improving your code. In this video you can follow along while I debug and explain object references in Java.

Common mistakes with object references

  • Trying to change an immutable value by reference.
  • Trying to change a primitive variable by reference.
  • Expecting the real object won't change when you change a mutable object parameter in a method.

What to remember about object references

  • Java always passes parameter variables by value.
  • Object variables in Java always point to the real object in the memory heap.
  • A mutable object’s value can be changed when it is passed to a method.
  • An immutable object’s value cannot be changed, even if it is passed a new value.
  • “Passing by value” refers to passing a copy of the value.
  • “Passing by reference” refers to passing the real reference of the variable in memory.

Learn more about Java

  • Get more quick code tips: Read all of Rafael's posts in the JavaWorld Java Challengers series.
  • Learn more about mutable and immutable Java objects (such as String and StringBuffer) and how to use them in your code.
  • Es könnte Sie überraschen, zu erfahren, dass die primitiven Typen von Java umstritten sind. In dieser Funktion spricht sich John I. Moore dafür aus, sie zu behalten und zu lernen, sie gut zu verwenden.
  • Bauen Sie Ihre Java-Programmierkenntnisse im Java Dev Gym weiter aus.
  • Wenn Sie gerne Java-Vererbung debuggen, sehen Sie sich weitere Videos in Rafaels Java Challenges-Video-Wiedergabeliste an (Videos in dieser Serie sind nicht mit JavaWorld verbunden).
  • Möchten Sie an stressfreien Projekten arbeiten und fehlerfreien Code schreiben? Besuchen Sie das NoBugsProject, um eine Kopie von No Bugs, No Stress zu erhalten - Erstellen Sie lebensverändernde Software, ohne Ihr Leben zu zerstören .

Diese Geschichte: "Geht Java als Referenz oder als Wert?" wurde ursprünglich von JavaWorld veröffentlicht.