Speicherzustände Java?

1 Antwort

Deine Bilder sind zu klein, als dass ich darauf etwas erkennen könnte. Darauf gehe ich an dieser Stelle also nicht ein.

Vorbereitung:

Diese Zeilen:

Wrapper w1 = new Wrapper();
Wrapper w2 = w1;
// ...

darf man erst einmal nicht übersehen. Im Grunde wird ein neues Objekt des Typs Wrapper erstellt und eine Variable w2, die folgend auf dasselbe Objekt verweisen soll, wie w1. Egal nun, über welche der beiden Variablen eine Änderung vorgenommen wird, es ist stets dasselbe Objekt betroffen. Erst bei einer Neudefinition von einer der beiden Variablen, würde es zu einem Bruch kommen. Näheres dazu weiter unten.

Was passiert in der Methode f:

Beim ersten Aufruf werden ihr der Wrapper (mit i=1), die 3 und das Array { 4, 5 } übergeben. In Java sind alle Werteübergaben by value. Das bedeutet, der Parameter x mag zwar den Wert 3 haben, doch diese 3 ist nur eine Wertekopie der Variable x von außerhalb. Wenn sich x in der Methode verändert, verändert sich die Variable x außen nicht.

Im ersten Schritt wird der Parameter x also mit einem neuen Wert (4) überschrieben.

x = a[0];

Dann wird der aktuelle Wert von dem Attribut des Wrapper-Objekts geholt (2) und im Array an erster Stelle gespeichert.

a[0] = w.getI();

Abermals handelt es sich nur um eine Wertübergabe - getI liefert nur einen primitiven Wert. Sollte sich das erste Element des Arrays folgend nochmals ändern, hat das keinerlei Einfluss auf das Wrapper-Objekt. Auf die Wirkung auf das Array hingegen komme ich noch zu sprechen.

In Zeile 3 wird der Zustand des Wrapper-Objekts geändert. Das Attribut i hat danach den Wert 4.

w.setI(x);

Nun hast du ein paar Zeilen weiter oben gelesen, Parameter würden in Java stets pass by value übergeben werden. Das sollte ja bedeuten, dass von jedem Parameter immer nur eine Kopie gemacht wird, sodass auf die äußeren Objekte, die übergeben wurden, kein Einfluss besteht.

Das heißt nochmals deutlich im Klartext, man müsste bei diesem Beispiel folgendes Ergebnis erwarten:

class Car {
  public int numberOfWheels = 4;
}

class ServiceStation {
  public void change(Car car, int numberOfWheels) {
    car.numberOfWheels = numberOfWheels;
  }
}

// main:
Car car = new Car();
ServiceStation station = new ServiceStation();
station.change(car, 3);
System.out.println(car.numberOfWheels); // <<< should be 4?

Dem ist aber keinesfalls so. Die Methode change ändert durchaus den Zustand des Objekts (die neue Radanzahl wäre 3). Das liegt daran, dass Java implizit mit einer Art Zeiger je Objekt arbeitet. Einen solchen Zeiger kann man sich hierbei als ein Element vorstellen, welches auf ein Objekt zeigt.

[Variablenname] --- zeigt auf --> [Zeiger] --- zeigt auf --> [Objekt]

Über den Zeiger werden die Methoden und Attribute des Objekts ganz normal aufgelöst / angesprochen. Bei der Parameterübergabe wird implizit einfach eine Kopie des Zeigers erstellt (nicht auf das Objekt). Diese Kopie zeigt wie das Original auf dasselbe Objekt.

Würde man allerdings eine Neudefinition der Variable (bzw. des Parameters) vornehmen, würde man den ursprünglichen Zeiger nicht mehr zur Verfügung haben und auf ein neues Objekt verweisen. Ein Beispiel dazu:

class Car {
  public int numberOfWheels = 4;
}

class ServiceStation {
  public void change(Car car, int numberOfWheels) {
    car = new Car(); // redefinition of variable
    car.numberOfWheels = numberOfWheels;
  }
}

// main:
Car car = new Car();
ServiceStation station = new ServiceStation();
station.change(car, 3);
System.out.println(car.numberOfWheels); // <<< 4

Tatsächlich ist für dich als Java-Programmierer zunächst nur das Verhalten interessant. Die von mir erwähnten Begriffe (pass by value) sind nur Beiwerk, welches beim Vergleich mit anderen Programmiersprachen relevanter wird. Es gibt nämlich Sprachen (wie C++ oder PASCAL), die durchaus auch noch andere Formen unterstützen.

Zuletzt noch die Lösung für den zweiten Aufruf von f:

Das x (außen) bleibt nach wie vor 3, innen nimmt es die 1 an. Durch die vorherige Änderung des Wrapper-Objekts (über w1) liegt der Attributwert anfangs bei 2 und die erste Stelle des Arrays wird mit 4 überschrieben. Das Wrapper-Objekt bekommt für sein Attribut als neuen Wert die 1 zugewiesen.

vikiller01 
Fragesteller
 17.11.2019, 11:17

Hilfreichste Antwort. Vielen Dank

0