Lernpfad:Objektorientierte Programmierung mit Java/Referenzen

Aus Informatik-Box
Zur Navigation springen Zur Suche springen

Objektreferenzen

Jede Objektinstanz einer Klasse wird von Java im Speicher abgelegt. Für jede Instanz wird dazu eine festgelegte Anzahl Bits reserviert, abhängig von den deklarierten Objektvariablen.

Wird dasselbe Objekt nun einer neuen Variablen zugewiesen, als Parameter einer Methode übergeben oder als neue Objektvariable gespeichert, wird keine Kopie des Objektes angelegt, sondern eine Referenz erzeugt. Das bedeutet, dass nur die Speicheradresse der ersten Objektinstanz im Speicher abgelegt wird. Man spricht auch von einem Zeiger auf das Objekt.

Postfachschraenke.jpg
Man kann sich das wie einen Abholschein der Post vorstellen, auf der steht, dass man ein Paket bei der Poststelle abholen kann. Die Referenznummer auf dem Schein ist ein Zeiger auf den Ort, an dem das Paket von Postboten abgelegt wurde. Der Postmitarbeiter kennt die Referenznummer auch - hat also auch einen Zeiger auf das Paket - und weiß, wo er im Lager suchen muss, um es herauszugeben.

Würde der Mitarbeiter etwas an dem Paket verändern, dann würdest du die Veränderung auch sehen, sobald du das Paket erhalten hast, da es sich um dasselbe Objekt handelt.

Referenzen erzeugen

Prinzipiell kann jede Variable, die als Typ keinen der generischen Datentypen hat, als Referenz betrachtet werden. Jede Zuweisung der Variablen zu einer anderen Variablen erzeugt eine weitere Referenz auf dieselbe Objektinstanz.

public class Zahl {
    private int zahl;
    public Zahl( int pZahl ) {
        zahl = pZahl;
    }
    public void setZahl( int pZahl ) {
       zahl = pZahl;
    }
    public int getZahl() {
        return zahl;
    }
}

public class ZahlenTester {
    public ZahlenTester() {
        // Erzeugen einer neuen Instanz von Zahl
        Zahl a = new Zahl(999);
        // Erzeugen einer Referenz auf die bestehende Objektinstanz von Zahl
        Zahl b = a;

        System.out.println("a: " + a.getZahl()); // a: 999
        System.out.println("b: " + b.getZahl()); // b: 999
        b.setZahl(111);
        System.out.println("a:" + a.getZahl()); // a: 111
        System.out.println("b:" + a.getZahl()); // b: 111
    }
}

Referenzen benutzen

Hat man eine Referenz auf ein Objekt erzeugt, dann kann man sie nutzen, um Methoden auf dem referenzierten Objekt aufzurufen. Dazu wird die Punktnotation verwendet. Im Quelltext-Auszug oben wurde etwa eine Referenz a auf ein Objekt der Klasse Zahl erzeugt (Zeile 17). Dann wurde auf dem referenzierten Objekt die Methode public int getZahl() aufgerufen (Zeile 21).

Sichtbarkeiten und Methodenaufrufe

Die Methode public int getZahl() konnte in diesem Beispiel aufgerufen werden, da ihre Sichtbarkeit public ist. Das bedeutet, dass alle fremden Objekte, die eine Referenz auf das Objekt besitzen, die Methode aufrufen dürfen. Das Gegenteil ist die Sichtbarkeit private. Sie verbietet allen anderen Objekten den Zugriff. Nur das Objekt selbst darf als private deklarierte Methoden auf sich selber aufrufen. Außerdem gibt es noch eine dritte Sichtbarkeit, die vorwiegend bei der Vererbung eine Rolle spielt.

public
Die Methode darf ohne Einschränkungen aufgerufen werden.
protected
Die Methode darf nur vom Objekt der Klasse selber und von Unterklassen benutzt werden. Von "außen", also über eine Referenz auf das Objekt, darf die Methode nicht aufgerufen werden.
private
Die Methode darf nur von Objekten der Klasse auf sich selber benutzt werden. Auch Unterklassen dürfen die Methode nicht benutzen.

Referenzen löschen

Ist in einer Variablen eine Referenz auf ein Objekt gespeichert, dann kann diese gelöscht werden, indem der Variablen der Wert null zugewiesen wird.

// Variable a speichert eine Referenz auf ein Objekt der Klasse Zahl
Zahl a = new Zahl(999);
// Variable b speichert eine Referenz auf dasselbe Objekt wie a
Zahl b = a;
// Referenz a löschen
a = null;
// b referenziert das Objekt immer noch
b.nextInt();

Referenzierung verhindern

Da von Java bei der Nutzung von Objekten in der Regel Referenzen angelegt und verwendet werden, kann es unter Umständen zu unerwünschten Effekten kommen. Manchmal möchte man eben doch eine Kopie einer Objektinstanz haben und keine Referenz.

Im Beispiel oben wirkt sich jede Änderung an a auch auf b aus (da es sich um Referenzen auf dasselbe Objekt handelt).

Soll das explizit verhindert werden, muss b als neue Objektinstanz von Zahl initialisiert und der Objektzustand von a nach b kopiert werden.

public class ZahlenTester {
    public ZahlenTester() {
        // Erzeugen einer neuen Instanz von Zahl
        Zahl a = new Zahl(999);
        // Erzeugen eines neuen Objekts mit demselben Zustand wie das erste Objekt
        Zahl b = new Zahl(a.getZahl());

        System.out.println("a: " + a.getZahl()); // a: 999
        System.out.println("b: " + b.getZahl()); // b: 999
        b.setZahl(111);
        System.out.println("a:" + a.getZahl()); // a: 999
        System.out.println("b:" + a.getZahl()); // b: 111
    }
}