Java this! Ein verwirrendes Schlüsselwort?

Keylearnings:

  • Die Bedeutung von Java this.
  • Was sind Referenzen?
  • Wofür eigentlich Java this?
  • Wie du mit Hilfe von Java this Namenskonflikte vermeidest.
  • Wie du mit Hilfe des Schlüsselworts this einen Konstruktor aufrufst.
  • Wie du Java this als Übergabeparameter verwendest.

Es gibt Dinge, die mich verwirren.

Zum Beispiel fliegende Katzen, kleine dünne Menschen, die zwei Jumbo Pizzen verdrücken oder auch das Java Schlüsselwort this.

Zumindest die Verwirrung um das Java this Schlüsselwort möchte ich in diesem Artikel auflösen.

Das Schlüsselwort Java this

Um das Java this Schlüsselwort zu verstehen, müssen wir uns zunächst nochmal darüber unterhalten was eigentlich passiert, wenn wir mittels des new Operators ein Objekt erzeugen.

Dazu benötigen wir als erstes eine Klasse, mit der wir experimentieren können. Schauen wir uns dazu einen echten Klassiker an, nämlich eine Klasse Kraftfahrzeug.

public class Kraftfahrzeug {
	
	public int ps = 0;
	private int verbrauch = 0;
	private int geschwindigkeit  = 0;

}

Die Klasse enthält die zwei privaten Attribute verbrauch und Geschwindigkeit und außerdem, etwas was wir im echten Leben NIEMALS machen sollten, ein öffentliches Attribut ps.

Ziemlich nutzlos! Aber lass uns dennoch zwei Instanzen dieser Klasse erzeugen.

1: Kraftfahrzeug fahrzeug1 = new Kraftfahrzeug();
2: Kraftfahrzeug fahrzeug2 = new Kraftfahrzeug();

Der new Operator sorgt dafür, dass Speicher für die zu erzeugenden Objekte reserviert wird.

Nach den beiden Anweisungen von oben haben wir also zwei Speicherbereiche, in denen wir jeweils Platz für die Kraftfahrzeug Attribute ps, verbrauch und geschwindigkeit haben.

Okay, geben wir beide Variablen auf dem Bildschirm aus und sehen mal nach, was deren Inhalt ist.

System.out.println(fahrzeug1);
System.out.println(fahrzeug2);

Als Bildschirmausgabe erhalten wir:

Kraftfahrzeug@2a139a55
Kraftfahrzeug@15db9742

Hmm, what’s the fuck??

Was ist hier passiert? Welchen Inhalt haben die Variablen fahrzeug1 und fahrzeug2?

Das was wir hier sehen nennt man Referenz. Eine Referenz kann man sich vorstellen wie eine Adresse, unter der wir den für ein Objekt reservierten Speicherbereich finden.

Unsere Bildschirmausgabe von oben können wir also als die Adressen der Speicherbereiche verstehen, in denen wir die Objekte fahrzeug1 und fahrzeug2 speichern.

java this Referenz

Also Merke: Wenn wir Objekte einer Variablen zu weisen, dann weisen wir der Variable nicht den Inhalt des Objekts zu, sondern lediglich einen Verweis auf die Position im Speicher, an der es gespeichert ist.

Schauen wir uns die Konsequenz dieser Feststellung an einem Beispiel an:

1: Kraftfahrzeug fahrzeug3 = fahrzeug1;	
2: fahrzeug3.ps = 120;
3: fahrzeug1.ps = 160;
4: System.out.println(fahrzeug3.ps);
5: System.out.println(fahrzeug1.ps);

In der ersten Zeile weisen wir fahrzeug1, einer neu erzeugten Kraftfahrzeug Variablen fahrzeug3 zu.

Anschließend weisen wir dem fahrzeug3 die PS Zahl 120 und dem fahrzeug1 die PS Zahl 160 zu und geben beide PS Zahlen auf dem Bildschirm aus.

Mit welcher Ausgabe rechnest du?

Vielleicht?

120
160

Mal sehen? Lass uns das Programm starten! Trommelwirbel!! Die Programmausgabe lautet:

160
160

Hmm, sowohl das fahrzeug1 als auch das fahrzeug3 haben 160PS. Merkst du woran es liegt?

Wir haben für fahrzeug3 keine neue Instanz mittels des new Operators erzeugt und somit auch keinen Speicher reserviert sondern lediglich fahrzeug1 der Variablen fahrzeug3  zugewiesen.

Geben wir beide Variablen auf dem Bildschirm aus, so erhalten wir:

Kraftfahrzeug@2a139a55
Kraftfahrzeug@2a139a55

Beide Variablen zeigen also auf den gleichen Speicherbereich und ändern deshalb auch die gleichen Attribute.

java this referenz

Deshalb setzen wir zwar in Zeile zwei, das ps Attribut auf 120, da wir in Zeile drei aber den gleichen Speicherbereich ansprechen wird dieser Wert sofort mit dem Wert 160 überschrieben.

Aber okay, okay wir wollten über das Java this Schlüsselwort plaudern. Also was hat das alles mit dem Java this Schlüsselwort zu tun?

Nun ja, das Java this Schlüsselwort liefert auch nichts anderes als eine Referenz und zwar eine Referenz auf das Objekt, in dem wir uns befinden.

Warte! Ich zeigs dir. Lass und die Klasse von oben um eine Methode getMe erweitern.

public class Kraftfahrzeug {
	
    private int ps = 0;
    private int verbrauch = 0;
    private int geschwindigkeit  = 0;
	
     public Kraftfahrzeug getMe(){
	return this;
     }

}

Der Rückgabewert der Methode getMe ist vom Typ Kraftfahrzeug, d.h. die Methode ist in der Lage eine Referenz auf einen Speicherplatz, in dem ein Kraftfahrzeug gespeichert ist zurück zuliefern.

Im Methodenrumpf wird lediglich die this Referenz über ein return zurückgegeben.

Und halt dich fest, hier die Auflösung des Geheimnisses um das Schlüsselwort this.

Das Schlüsselwort this liefert eine Referenz auf den Speicherbereich, in dem ein Objekt gespeichert ist zurück.

Sehen wir uns auch das anhand eines Beispielprogramms an.

1: System.out.println(fahrzeug1);
2: System.out.println(fahrzeug1.getMe());

Welche Ausgabe erwartest du?

In der ersten Zeile geben wir die Referenz auf den Speicherbereich, in dem das Objekt fahrzeug1 gespeichert ist aus.

Und in der zweiten Zeile?

Ebenso! Nur das wir hier die Referenz mit Hilfe des this Schlüsselwortes in der getMe() Methode zurückliefern.

Hier zum Beweis die Bildschirmausgabe.

Kraftfahrzeug@2a139a55
Kraftfahrzeug@2a139a55

Anwendungen des Java this Schlüsselwortes

Soweit so gut! Aber wofür können wir das jetzt gebrauchen?

Java this zum Auflösen von Namenskonflikten

Das erste und berühmteste Anwendungsgebiet von java this ist das Auflösen von Namenskonflikten insbesondere bei Konstruktoren und setter Methoden.

Hier zunächst ein Beispiel einer setter Methode, so wie es NICHT funktioniert.

1: public void setGeschwindigkeit(int geschwindigkeit) {
2:	geschwindigkeit = geschwindigkeit;
3:}

Die Methode besitzt einen Integer-Parameter mit dem Namen geschwindigkeit. Und genau das ist ein Problem!

In der Klasse Kraftfahrzeug gibt es nämlich ebenfalls ein Attribut mit dem Namen geschwindigkeit, dem wir über unsere setter Methode einen Wert zu weisen wollen.

Innerhalb von setGeschwindigkeit ist aber nur der Übergabeparameter mit dem Namen geschwindigkeit bekannt. Wie greifen wir also aus der setter-Methode auf das Attribut geschwindigkeit zu?

Es wird dich überraschen. Die Lösung ist Java this!

Wir müssen die zweite Zeile entsprechend anpassen.

1: public void setGeschwindigkeit(int geschwindigkeit) {
2:	this.geschwindigkeit = geschwindigkeit;
3:}

Jetzt wird der Wert des Übergabeparameters geschwindigkeit dem Attribut geschwindigkeit zu gewiesen.

Java this zum Aufruf von Methoden und Konstruktoren

Ein weiterer Fall, bei dem wir das Schlüsselwort this verwenden ist der Aufruf überschriebener Konstruktoren.

Bis jetzt haben wir in unserer Kraftfahrzeug Klasse noch keinen Konstruktor implementiert, was dazu führt, dass alle Attribute nach Erzeugung eines Objektes den Wert 0 haben.

Holen wir das nach und versehen unsere Klasse zum einen mit einem Standard-Konstruktor und zum anderen mit einem Konstruktor, mit dem wir die Attribute ps, geschwindigkeit und verbrauch initialisieren können.

Beginnen wir mit dem wenig spektakulärem Standard-Konstruktor.

public Kraftfahrzeug(){} 

Und als nächstes der Konstruktor um die Attribute zu initialisieren.

public Kraftfahrzeug(int ps, int verbrauch, int geschwindigkeit) {
    this.ps = ps;
    this.verbrauch = verbrauch;
    this.geschwindigkeit = geschwindigkeit;
}

Um Namenskonflikte zwischen der Parameterliste des Konstruktors und den Attributen der Klasse zu vermeiden, haben wir auch hier wieder das Schlüsselwort this verwendet.

Mit Hilfe des neuen Konstruktors haben wir jetzt die Möglichkeit Fahrzeug-Objekte mit initialisierten Attributen zu erzeugen.

Kraftfahrzeug fahrzeug = new Kraftfahrzeug(80,6,240);

Hiermit haben wir ein Kraftfahrzeug mit 80PS, 6Liter Verbrauch und einer Höchstgeschwindigkeit von 240 erzeugt.

Eine andere Möglichkeit die Attribute zu initialisieren liefert das this Schlüsselwort.

Mit Hilfe von this können wir den Konstruktor Kraftfahrzeug(int ps, int verbrauch, int Geschwindigkeit) aus dem Standardkonstruktor heraus aufrufen.

Dazu müssen wir den Standardkonstruktor um einen this Aufruf wie folgt erweitern.

public Kraftfahrzeug(){
	this(80,6,240);
}

Nach dieser Änderung wird mit der Anweisung

Kraftfahrzeug fahrzeug = new Kraftfahrzeug();

ein Kraftfahrzeug mit 80PS, 6Liter Verbrauch und einer Höchstgeschwindigkeit von 240 erzeugt.

Die Anweisung this(80,6,240) sucht in der Klasse nach einem Konsruktor mit drei Parametern und ruft diesen mit den entsprechenden Argumenten auf.

In unserem Fall wird also der Konstruktor Kraftfahrzeug mit den Argumenten 80,6 und 240 aufgerufen.

Java this als Argument einer Methode

Eine weitere Verwendung von Java this ist die Übergabe als Parameter an eine Methode.

Welchen Sinn macht das?

Kreieren wir  zur Demonstration eine Klasse Waschanlage mit einer Methode fahrzeugWaschen.

class Waschanlage {

   public void fahrzeugWaschen(Kraftfahrzeug fahrzeug){
	//Methode fahrzeugWaschen
   }
	
}

Mit Implementierungs-Details der Methode fahrzeugWaschen müssen wir uns an dieser stelle nicht beschäftigen.

Unser Ziel ist im folgenden die Klasse Kraftfahrzeug um eine Methode waschen zu erweitern, welche die Methode fahrzeugWaschen aus der Klasse Waschanlage aufruft.

Folgendes soll also möglich sein:

Kraftfahrzeug fahrzeug = new Kraftfahrzeug();
fahrzeug.waschen();

Wie ist die waschen Methode zu implementieren?

Wir wollen genau das Kraftfahrzeug waschen, aus dem wir die Methode heraus aufrufen, daher müssen wir auch eine Referenz auf genau dieses Kraftfahrzeug an die Methode fahrzeugWaschen übergeben.

Und jetzt rate mal, wie wir das hinbekommen? Right! Mit Java this. Lass uns die Klasse Kraftfahrzeug um die Methode waschen erweitern.

public void waschen(){
1:   Waschanlage waschAnlage = new Waschanlage();
2:   waschAnlage.fahrzeugWaschen(this);
e: }

Da wir unser Kraftfahrzeug in einer Waschanlage waschen wollen, legen wir zunächst in Zeile Eins die Instanz einer Waschanlage an.

Als nächstes rufen wir dann in Zeile Zwei die in der Waschanlage implementierte Methode fahrzeugWaschen auf, die als Übergabeparameter eine Referenz auf ein Kraftfahrzeug Objekt erwartet.

Diese Referenz soll auf das Objekt zeigen, aus dem wir die Methode fahrzeugWaschen heraus aufrufen. Und genau das liefert das Schlüsselwort this.

Noch nicht klar? Okay, implementieren wir die gleiche Funktionalität erneut, aber ohne das Schlüsselwort this.

1: Kraftfahrzeug fahrzeug = new Kraftfahrzeug();
2: Waschanlage anlage = new Waschanlage();
3: anlage.fahrzeugWaschen(fahrzeug);

Dieser Code liefert das gleiche Ergebnis wie der Aufruf von

fahrzeug.waschen();

Warum das??

Weil die Referenz, die in der Variable fahrzeug gespeichert ist, die selbe ist, die wir in der Methode waschen aus der Klasse Kraftfahrzeug, über das this Schlüsselwort an die Methode fahrzeugWaschen aus der Klasse Waschanlage übergeben.

Ich hoffe ich konnte in diesem Artikel die Verwirrung um das java Schlüsselwort ein wenig mildern. Merke dir einfach: Dass Schlüsselwort this liefert eine Referenz auf das Objekt, in dem du dich befindest zurück.

Ich freue mich auf deine Fragen im Kommentarbereich.

Hat dir der Artikel gefallen? Dann folge uns am besten gleich auf Facebook!

Hallo ich bin Kim und ich möchte ein großer Programmierer werden. Machst du mit?

Kommentare (36)

  • Antworte

    nice geschrieben
    hat mir sehr weitergeholfen danke

    • Hi Jakob, Danke für dein Feedback. Freue mich wenn ich weiterhelfen kann. Viele Grüße Kim

  • Antworte

    Super erklärt! Hab das wort ‚this‘ echt gehasst. Vielen Dank!

    • Hi Kristin, sehr gerne! Viele Grüße Kim

  • Antworte

    Super gemacht Kim. Hat geholfen. Danke.

  • Antworte

    Wow, ich muss sagen mir hat das sehr geholfen, verständlich erklärt und mit guten Beispielen ergänzt. Ein grosses Lob an dich Kim!!!

    • Vielen Dank Dominic!

  • Antworte

    Hallo,
    danke für den Artikel!
    Ist Kim nicht ein Frauenname?

    • Hallo Robert,gerne! Nein, es ist beides. Allerdings habe ich deshalb als Zweit-Namen Peter. Viele Grüße Kim

  • Antworte

    Super erklärt. Besten Dank!!!!

    • sehr gerne!

  • Antworte

    Danke Kim, leicht und verständlich, hat mich abgeholt, Klasse !!!

    • Viele Dank! Ich freue mich sehr über deine Rückmeldung.

  • Antworte

    Hey Kim,
    sehr guter Artikel! Dank dir ist mir jetzt endlich klar, wofür this zu gebrauchen ist 🙂

    • Vielen Dank!

  • Antworte

    Super erklärt. Genial verständliche Beispiele. Vielen vielen Dank.

    • Vielen Dank!

  • Antworte

    Super hilfreich, aber 240 mit 80 PS ist etwas zu optimistisch ;D

    • Hallo Paul, ich kenne mich da leider nicht so gut. Ich besitze kein Auto 😉 Viele Grüße Kim

  • Antworte

    top geschrieben und sehr strukturiert erklärt

    • Dankeschön!

  • Antworte

    Hallo, ich bin nicht gerade ein OOP Freak, und die Notwendigkeit von „this“ habe ich trotzdem nicht verstanden. Aber Du hast eine gute Art, die Dinge rüberzubringen.

    • Ich danke dir!

  • Antworte

    Trotzdem eine Kritik an der Nutzung von „this“ aber nicht an Dir,
    Beispiel:
    public void setGeschwindigkeit(int Geschwindigkeit) {
    Geschindigkeit = Geschwindigeit;
    }
    Der Compiler hat alle Informationen, um trotz der ungeschickten Wahl der Variablennamen damit umzugehen: Der Compiler weiß, dass der Übergabeparameter „Geschwindigkeit“ einen Wert enthält, aber innerhalb der Funktion nicht gesetzt werden kann. Daraus hätte er folgern können, dass der Parameter „Geschindigkeit“ nur rechts

    Geschwindigkeit = Geschwindigkeit;

    stehen kann. Für die Einführung von „this“ gibt es jedenfalls hier keinen Grund.

    PS ich stehe der ganzen OOP skeptisch gegenüber. Habe mehrere Bücher darüber gelesen und leider mit C++ angefangen.

    • Hallo Olaf, guter Einwand! Erst wenn eine gleichnamige Variabel innerhalb der Methode definiert würde, hätte man ein Problem. C++ ist super! Meiner Meinung nach aber auch deutlich komplizierter als Java und auch als die meisten anderen Sprachen (mit Ausnahme Assembler). Viele Grüße Kim

  • Antworte

    Im restlichen Code mit „this“ hatte ich das Problem zu erahnen, in welcher Relation es steht. Befinde ich mich direkt unter main() oder bin ich in einer anderen Klasse. Wer ruft wen von welchem Ort aus auf, das ist mir nicht klar geworden.

    und Codezeilen wie

    Waschanlage waschAnlage = new Waschanlage();

    in denen das Wort Waschanlage drei mal vorkommt, machen solchen Code nicht gerade verständlich, aber das scheint wohl ein generelles OO-Problem zu sein.

    Der letzte Satz hat es dann aber wieder gebracht:

    Das Schlüsselwort „this“ liefert eine Referenz auf das Objekt, in dem Du Dich befindest.

    Jetzt wo ich es schreibe, wird es wieder unklar. Wenn ich nicht weiß, wo ich mich befinde, dann muß ich im Sourcecode nachsehen, wo mein Cursor gerade blinkt. Ich denke, dass das nicht gemeint war.

    Gemeint ist möglicherweise:

    Mein Rechner arbeit Code ab und befindet sich im Objekt A und ruft eine Methode aus Objekt B auf. Dabei verwendet er als Übergabeparameter this, d.h. Objekt B.Methode(this). Dann weiß Methode(this) durch this, was sie bearbeiten soll, weil this eine Referenz auf das Objekt ist, das bearbeitet werden soll.

    oder so ähnlich. OOP ist echt, ähm, vorsichtig ausgedrückt: gewöhnungsbedürftig.
    Resumee für mich und nur für mich: this nicht verwenden, wenn Du nicht wirklich verstanden hast, wie es funktioniert.

    Habt Ihr denn keine Probleme damit?

    • Hallo Olaf, vielen Dank für deinen Kommentar. Und sorry für meine späte Antwort (WordPress hat den Kommentar irgendwie in den falschen Ordner gepackt). OOP macht sinn, da es ein Werkzeug ist um Komplexität zu verbergen. Um einen Motor zu verwenden, brauchst du nicht unbedingt genau zu wissen wie dieser tatsächlich funktioniert. Das ist beispielsweise in der prozeduralen Welt anders. Aber du hast trotzdem völlig recht OOP ist definitiv nicht die Lösung für alles. Nicht umsonst wurde in Java 8 und insbesondere Java 9 funktionale Elemente in die Sprache aufgenommen. Viele Grüße Kim

  • Antworte

    Als nächstes rufen wir dann in Zeile Zwei die in der Waschanlage implementierte Methode waschen auf, die als Übergabeparameter eine Referenz auf ein Kraftfahrzeug Objekt erwartet.

    Müsste es nicht heißen:
    Als nächstes rufen wir dann in Zeile Zwei die in der Waschanlage implementierte Methode fahrzeugWaschen auf, die als Übergabeparameter eine Referenz auf ein Kraftfahrzeug Objekt erwartet.

    • Hallo Jesaja, absolut richtig! Habe es geändert. Viele Grüße Kim

  • Antworte

    Genau das was ich gesucht habe und so einfach erklärt. Danke Dir!

  • Antworte

    Hallo Kim,
    als erfahrener Programmierer habe diesen Artikel sehr genau gelesen und ich muss echt sagen, dass ich diesen sehr gut finde. Er ist sehr verständlich und einfach zu lesen.

    Keep it up

    MFG
    Arne

    • Hallo Arne, ich danke dir vielmals. Viele Grüße Kim

  • Antworte

    MEGAAA Danke

    • Hallo Pablo, gerne! Viele Grüße Kim

Hinterlasse ein Kommentar