Rheinwerk Computing < openbook >


 
Inhaltsverzeichnis
Materialien
Vorwort
1 Java ist auch eine Sprache
2 Imperative Sprachkonzepte
3 Klassen und Objekte
4 Arrays und ihre Anwendungen
5 Der Umgang mit Zeichenketten
6 Eigene Klassen schreiben
7 Objektorientierte Beziehungsfragen
8 Ausnahmen müssen sein
9 Geschachtelte Typen
10 Besondere Typen der Java SE
11 Generics<T>
12 Lambda-Ausdrücke und funktionale Programmierung
13 Architektur, Design und angewandte Objektorientierung
14 Java Platform Module System
15 Die Klassenbibliothek
16 Einführung in die nebenläufige Programmierung
17 Einführung in Datenstrukturen und Algorithmen
18 Einführung in grafische Oberflächen
19 Einführung in Dateien und Datenströme
20 Einführung ins Datenbankmanagement mit JDBC
21 Bits und Bytes, Mathematisches und Geld
22 Testen mit JUnit
23 Die Werkzeuge des JDK
A Java SE-Module und Paketübersicht
Stichwortverzeichnis


Download:

- Listings, ca. 2,7 MB


Buch bestellen
Ihre Meinung?



Spacer
<< zurück
Java ist auch eine Insel von Christian Ullenboom

Einführung, Ausbildung, Praxis
Buch: Java ist auch eine Insel


Java ist auch eine Insel

Pfeil6 Eigene Klassen schreiben
Pfeil6.1 Eigene Klassen mit Eigenschaften deklarieren
Pfeil6.1.1 Attribute deklarieren
Pfeil6.1.2 Methoden deklarieren
Pfeil6.1.3 Verdeckte (shadowed) Variablen
Pfeil6.1.4 Die this-Referenz
Pfeil6.2 Privatsphäre und Sichtbarkeit
Pfeil6.2.1 Für die Öffentlichkeit: public
Pfeil6.2.2 Kein Public Viewing – Passwörter sind privat
Pfeil6.2.3 Wieso nicht freie Methoden und Variablen für alle?
Pfeil6.2.4 Privat ist nicht ganz privat: Es kommt darauf an, wer’s sieht *
Pfeil6.2.5 Zugriffsmethoden für Attribute deklarieren
Pfeil6.2.6 Setter und Getter nach der JavaBeans-Spezifikation
Pfeil6.2.7 Paketsichtbar
Pfeil6.2.8 Zusammenfassung zur Sichtbarkeit
Pfeil6.3 Eine für alle – statische Methoden und statische Attribute
Pfeil6.3.1 Warum statische Eigenschaften sinnvoll sind
Pfeil6.3.2 Statische Eigenschaften mit static
Pfeil6.3.3 Statische Eigenschaften über Referenzen nutzen? *
Pfeil6.3.4 Warum die Groß- und Kleinschreibung wichtig ist *
Pfeil6.3.5 Statische Variablen zum Datenaustausch *
Pfeil6.3.6 Statische Eigenschaften und Objekteigenschaften *
Pfeil6.4 Konstanten und Aufzählungen
Pfeil6.4.1 Konstanten über statische finale Variablen
Pfeil6.4.2 Typunsichere Aufzählungen
Pfeil6.4.3 Aufzählungstypen: typsichere Aufzählungen mit enum
Pfeil6.5 Objekte anlegen und zerstören
Pfeil6.5.1 Konstruktoren schreiben
Pfeil6.5.2 Verwandtschaft von Methode und Konstruktor
Pfeil6.5.3 Der Standard-Konstruktor (default constructor)
Pfeil6.5.4 Parametrisierte und überladene Konstruktoren
Pfeil6.5.5 Copy-Konstruktor
Pfeil6.5.6 Einen anderen Konstruktor der gleichen Klasse mit this(…) aufrufen
Pfeil6.5.7 Immutable-Objekte und Wither-Methoden
Pfeil6.5.8 Ihr fehlt uns nicht – der Garbage-Collector
Pfeil6.6 Klassen- und Objektinitialisierung *
Pfeil6.6.1 Initialisierung von Objektvariablen
Pfeil6.6.2 Statische Blöcke als Klasseninitialisierer
Pfeil6.6.3 Initialisierung von Klassenvariablen
Pfeil6.6.4 Eincompilierte Belegungen der Klassenvariablen
Pfeil6.6.5 Exemplarinitialisierer (Instanzinitialisierer)
Pfeil6.6.6 Finale Werte im Konstruktor und in statischen Blöcken setzen
Pfeil6.7 Zum Weiterlesen
 

Zum Seitenanfang

6    Eigene Klassen schreiben Zur vorigen ÜberschriftZur nächsten Überschrift

»Das Gesetz ist der abstrakte Ausdruck des allgemeinen an und für sich seienden Willens.«

– Georg Wilhelm Friedrich Hegel (1770–1831)

In den letzten Kapiteln haben wir viel über Objektorientierung erfahren, aber eher von der Benutzerseite her. Wir haben gesehen, wie Objekte aufgebaut werden, und auch einfache Klassen mit statischen Methoden haben wir implementiert. Es wird Zeit, das Wissen um alle objektorientierten Konzepte zu vervollständigen und eigene, benutzerdefinierte Datentypen aufzubauen.

 

Zum Seitenanfang

6.1    Eigene Klassen mit Eigenschaften deklarieren Zur vorigen ÜberschriftZur nächsten Überschrift

Die Deklaration einer Klasse leitet das Schlüsselwort class ein. Im Rumpf der Klasse lassen sich deklarieren:

  • Attribute (Variablen)

  • Methoden

  • Konstruktoren

  • Klassen- sowie Exemplarinitialisierer

  • geschachtelte Klassen, Schnittstellen und Aufzählungen

Eine ganz einfache Klassendeklaration

Wir wollen die Konzepte der Klassen und Schnittstellen an einem kleinen Spiel verdeutlichen. Beginnen wir mit dem Spieler, den die Klasse Player repräsentiert:

Listing 6.1    src/main/java/com/tutego/insel/game/v1/Player.java, Player

class Player { }

Die Klasse hat einen vom Compiler generierten Konstruktor, und new Player() erzeugt aus diesem Bauplan ein Exemplar. Details zum Konstruktor folgen in Abschnitt 6.5.3, »Der Standard-Konstruktor (default constructor)«.

 

Zum Seitenanfang

6.1.1    Attribute deklarieren Zur vorigen ÜberschriftZur nächsten Überschrift

Diese Player-Klasse hat bisher keine Attribute und kann daher keine Zustände speichern. Geben wir dem Spieler zwei Attribute: eines für den Namen und ein zweites für einen Gegenstand, den er trägt. Die Datentypen sollen beide String sein:

Listing 6.2    src/main/java/com/tutego/insel/game/v2/Player.java, Player

class Player {

String name;

String item;

}
[»]  Hinweis

Bei Objektvariablen ist kein var möglich, die Datentypen müssen genannt sein.

Eine zweite Klasse, Playground, erzeugt in der statischen main(…)-Methode für den mutigen Spieler ein Player-Objekt, schreibt und liest die Attribute:

Listing 6.3    src/main/java/com/tutego/insel/game/v2/Playground.java, Playground

class Playground {



public static void main( String[] args ) {

Player p = new Player();

p.name = "Mutiger Manfred";

p.item = "Schlips";



System.out.printf( "%s nimmt einen %s mit.", p.name, p.item );

}

}
Das UML-Diagramm zeigt die Abhängigkeiten von »Playground« und »Player«.

Abbildung 6.1    Das UML-Diagramm zeigt die Abhängigkeiten von »Playground« und »Player«.

inline image  Spätestens, wenn zwei Klassen im Editor offen sind, möchten Tastaturjunkies schnell zwischen den Editoren wechseln. Das geht in Eclipse mit (Strg)+(F6). Allerdings ist dieses Tastaturkürzel in der Windows-Welt unüblich, sodass es umdefiniert werden kann, etwa zu (Strg)+(_ÿ). Das geht so: Unter WindowsPreferences aktivieren wir unter GeneralKeys das Kommando Next Editor (siehe Abbildung 6.2). Im Textfeld Binding lässt sich zunächst das alte Kürzel löschen und einfach (Strg)+(_ÿ) drücken. Das Ganze lässt sich auch für Previous Editor und (Strg)+(ª)+(_ÿ) wiederholen.

Tastaturkürzel in Eclipse einstellen

Abbildung 6.2    Tastaturkürzel in Eclipse einstellen

[»]  Hinweis

Eine spezielle Namenskonvention für Objektvariablen gibt es nicht. So ist es zwar möglich, zur Unterscheidung von lokalen Variablen ein Präfix wie f oder _ voranzustellen, doch sogar die Eclipse-Macher sind davon abgekommen. Objektvariablen können auch grundsätzlich wie Methoden heißen, doch ist das unüblich, da Variablennamen im Allgemeinen Substantive und Methoden Verben sind. Bezeichner können auch nicht so heißen wie Schlüsselwörter.

Initialisierung von Attributen

Anders als lokale Variablen initialisiert die Laufzeitumgebung alle Attribute mit einem Standardwert:

  • 0 bei numerischen Werten und char

  • false bei boolean

  • null bei Referenzvariablen

Gefällt uns das nicht, lassen sich die Variablen mit einem Wert belegen:

class Player {

String name = "";

}

Ein "".equals(new Player().name) würde also true ergeben.

[+]  Designtipp

Es ist eine Gratwanderung, einfache Datentypen zu verwenden oder doch andere Objekte zu referenzieren. Wenn Player z. B. eine Postleitzahl speichert, wäre ein int (oder String) problematisch, da der Spieler auch eine PLZ-Validierung durchführen müsste, was nicht seine Aufgabe ist. Die allgemeine OOP-Regel lautet: Setze bei Daten, die validiert werden müssen und vielleicht auch mit anderen Attributen zusammenhängen, einen neuen Typ ein.

Gültigkeitsbereich, Sichtbarkeit und Lebensdauer

Lokale Variablen beginnen ihr Leben in dem Moment, in dem sie deklariert und initialisiert werden. Endet der Block, ist die lokale Variable nicht mehr gültig, und sie kann nicht mehr verwendet werden, da sie aus dem Sichtbarkeitsbereich verschwunden ist. Bei Objektvariablen ist das anders. Eine Objektvariable lebt ab dem Moment, in dem das Objekt mit new aufgebaut wurde, und sie lebt so lange, bis der Garbage-Collector das Objekt wegräumt. Sichtbar und gültig ist die Variable aber immer im gesamten Objekt und in allen Blöcken.[ 143 ](Das gilt nicht für statische Methoden und statische Initialisierungsblöcke, aber diese werden erst später vorgestellt. )

 

Zum Seitenanfang

6.1.2    Methoden deklarieren Zur vorigen ÜberschriftZur nächsten Überschrift

Zu Attributen gesellen sich Methoden, die üblicherweise auf den Objektvariablen arbeiten. Geben wir dem Spieler drei Methoden:

  • carry(String newItem): Der Spieler soll einen neuen Gegenstand tragen.

  • doesCarryAnything(): Fragt an, ob der Spieler irgendeinen Gegenstand trägt.

  • dropAll(): Der Spieler lässt alle Gegenstände fallen.

Anders als unsere bisherigen statischen Methoden werden diese drei Methoden für Player Objektmethoden sein, also den Modifizierer static nicht tragen.

Listing 6.4    src/main/java/com/tutego/insel/game/v3/Player.java, Player

class Player {



String name = "";

String item = "";



void carry( String newItem ) {

if ( newItem != null && !newItem.trim().isEmpty() )

item += newItem + ";";

}



boolean doesCarryAnything() {

return !item.isEmpty();

}



void dropAll() {

item = "";

}

}
Das Klassendiagramm von »Player« zeigt zwei Attribute und drei Methoden.

Abbildung 6.3    Das Klassendiagramm von »Player« zeigt zwei Attribute und drei Methoden.

Die Methode carry(String) fragt zunächst ab, ob der neu aufzunehmende Gegenstand newItem, der hier bei uns ein String ist, gültig ist, also nicht null und nicht leer ist. Ist er gültig, wird er an die existierende String-Objektvariable item angehängt und mit einem Semikolon abgeschlossen – das trennt die Einträge. Die Abfragemethode doesCarryAnything() testet, ob der Spieler etwas trägt, indem wir testen, ob der String item für die Gegenstände leer ist oder nicht. dropAll() setzt den String mit den Gegenständen auf den Leerstring zurück.

Testen wir die Methoden mit einem Spieler:

Listing 6.5    src/main/java/com/tutego/insel/game/v3/Hogwurz.java, main()

Player parry = new Player();

parry.name = "Parry Hotter";

System.out.println( parry.doesCarryAnything() );

parry.carry( "Denkarium" );

parry.carry( "Stein der Doofen" );

System.out.printf( "%s trägt: %s%n", parry.name, parry.item );

System.out.println( parry.doesCarryAnything() );

parry.dropAll();

System.out.println( parry.doesCarryAnything() );

parry.carry( "Das goldene Ei" );

System.out.printf( "%s trägt: %s%n", parry.name, parry.item );

Wie zu erwarten, ist die Ausgabe:

false

Parry Hotter trägt: Denkarium;Stein der Doofen;

true

false

Parry Hotter trägt: Das goldene Ei;

inline image  Um schnell von einer Methode (oder Variablen) zur anderen zu navigieren, zeigt (Strg)+(O) ein Outline an (dieselbe Ansicht wie in der Ansicht Outline). Im Unterschied zur Ansicht Outline lässt sich in diesem kleinen gelben Fenster mit den Cursor-Tasten navigieren, und ein (¢) befördert uns zur angewählten Methode oder zum angewählten Attribut. Wird in der Ansicht erneut (Strg)+(O) gedrückt, befinden sich dort auch die in den Oberklassen deklarierten Eigenschaften; sie sind grau. Und zusätzlich befinden sich hinter den Eigenschaften die Klassennamen.

[+]  JVM-Interna *

Jedes Objekt hat eigene Objektzustände, aber nicht jedes Objekt hat auch noch einmal den Code für die Methoden doppelt. Denn der Code ändert sich ja nicht für jedes Objekt. Intern ist es eher so, dass die Methoden nur einmal existieren und einen Verweis auf die Objektdaten bekommen, auf denen sie operieren können.

Methodenaufrufe und Nebeneffekte

Alle Variablen und Methoden einer Klasse sind in der Klasse selbst sichtbar. Das heißt, innerhalb einer Klasse werden die Objektvariablen und Methoden mit ihrem Namen verwendet. Somit greift die Methode doesCarryAnything(…) direkt auf das nötige Attribut item zu, um die Programmlogik auszuführen. Dies wird oft für Nebeneffekte (Seiteneffekte) genutzt. Die Methoden carry(String) und dropAll() ändern ausdrücklich eine Objektvariable und verändert so den Zustand des Objekts. doesCarryAnything() liest dagegen nur den Zustand, modifiziert ihn aber nicht. Methoden, die Zustände ändern, sollten das in der API-Beschreibung entsprechend dokumentieren.

Objektorientierte und prozedurale Programmierung im Vergleich

Entwickler aus der prozeduralen Welt haben ein anderes Denkmodell verinnerlicht, sodass wir an dieser Stelle die Besonderheit der Objektorientierung noch einmal verdeutlichen wollen. Während in der guten objektorientierten Modellierung die Objekte immer gleichzeitig Zustand und Verhalten besitzen, gibt es in der prozeduralen Welt nur Speicherbereiche, die referenziert werden; Daten und Verhalten liegen hier nicht zusammen. Problematisch wird es, wenn die prozedurale Denkweise in Java-Programmen abgebildet wird. Dazu ein Beispiel: Die Klasse PlayerData ist ein reiner Datencontainer für den Zustand, aber Verhalten wird hier nicht deklariert:

Listing 6.6    src/main/java/com/tutego/insel/oop/PlayerData.java

class PlayerData {

String name = "";

String item = "";

}

Anstatt nun die Methoden ordentlich, wie in unserem ersten Beispiel, mit an die Klasse zu hängen, würde in der prozeduralen Welt ein Unterprogramm genau ein Datenobjekt bekommen und von diesem Zustände erfragen oder ändern:

Listing 6.7    src/main/java/com/tutego/insel/oop/PlayerFunctions.java

class PlayerFunctions {



static void carry( PlayerData data, String newItem ) {

if ( newItem != null && !newItem.trim().isEmpty() )

data.item += newItem + ";";

}



static void dropAll( PlayerData data ) {

data.item = "";

}

}

Da die Unterprogramme nun nicht mehr an Objekte gebunden sind, können sie statisch sein. Genauso falsch wären aber auch Methoden (egal, ob statisch oder nicht) in der Klasse PlayerData, wenn sie ein PlayerData-Objekt übergeben bekommen.

Beim Aufruf ist dieser nichtobjektorientierte Ansatz gut zu sehen. Setzen wir in Tabelle 6.1 links den falschen und rechts den korrekt objektorientiert modellierten Weg ein:

Prozedural

Objektorientiert

PlayerData parry = new PlayerData();

parry.name = "Parry Hotter";

PlayerFunctions.carry( parry, "Schnatz" );

PlayerFunctions.dropAll( parry );
Player parry = new Player();

parry.name = "Parry Hotter";

parry.carry( "Schnatz" );

parry.dropAll();

Tabelle 6.1    Gegenüberstellung von prozeduraler und objektorientierter Programmierung

Ein Indiz für eine problematische objektorientierte Modellierung ist also, wenn externen Methoden Objekte übergeben werden, anstatt die Methoden selbst an die Objekte zu setzen.

 

Zum Seitenanfang

6.1.3    Verdeckte (shadowed) Variablen Zur vorigen ÜberschriftZur nächsten Überschrift

Führt eine Methode eine neue Variable ein, so kann der gleiche Variablenname nicht noch einmal in einem inneren Block verwendet werden. Folgendes führt zu einem Compilerfehler:

public static void main( String[] args ) {

int args = 1; // inline image Duplicate local variable args

}

Beim Verlassen eines Blocks ist der Variablenname jedoch wieder frei. Folgendes ist daher in Ordnung:

for ( int i = 0; i < 10; i++ )

System.out.println( i );

for ( int i = 0; i < 10; i++ )

System.out.println( i );

Grundsätzlich keine Probleme gibt es, wenn eine lokale Variable/Parametervariable genauso heißt wie eine Objektvariable. Wir sprechen in diesem Fall von einer verdeckten Variablen – im Englischen shadowed variable genannt.[ 144 ](https://docs.oracle.com/javase/specs/jls/se14/html/jls-6.html#jls-6.4) Der Compiler wird dann die lokale Variable nutzen und nicht mehr die Objektvariable.

[zB]  Beispiel

Die lokale Variable name aus toString() verdeckt die Objektvariable name.

class Player {

String name, item;

public String toString() {

String name = "Der Experte";

return name + " trägt " + item; // Der Experte trägt …

}

}

Verdeckte Variablen sind praktisch, denn ohne so ein Konzept könnte eine neu eingefügte Objektvariable schnell viele Methoden kaputt machen, die zufälligerweise im Rumpf ebenfalls den gleichen Namen nutzen.[ 145 ](Fast alle Programmiersprachen besitzen verdeckte Variablen. Eine Ausnahme ist TypeScript. )

Ein Nachteil ist das nur, wenn wir die lokale Variable gleichzeitig mit der Parametervariablen nutzen wollen, doch dafür gibt es Lösungen.

 

Zum Seitenanfang

6.1.4    Die this-Referenz Zur vorigen ÜberschriftZur nächsten Überschrift

In jeder Objektmethode und jedem Konstruktor[ 146 ](Sowie Exemplarinitialisierer, doch der Code landet im Konstruktor. ) steht eine Referenz mit dem Namen this bereit, die auf das eigene Exemplar zeigt. Mit dieser this-Referenz lassen sich elegante Lösungen realisieren, wie die folgenden Beispiele zeigen:

  • Die this-Referenz löst das Problem, wenn Parameter oder lokale Variablen Objektvariablen verdecken.

  • Liefert eine Methode als Rückgabe die this-Referenz auf das aktuelle Objekt, lassen sich Methoden der Klasse einfach hintereinandersetzen.

  • Mit der this-Referenz lässt sich einer anderen Methode eine Referenz auf uns selbst geben.

Überdeckte Objektvariablen nutzen

Trägt eine lokale Variable den gleichen Namen wie eine Objektvariable, so verdeckt sie diese; das haben wir eben im vorherigen Abschnitt gesehen. Das ist so weit nicht tragisch und wird nur dann zum Problem, wenn später Zugriff auf die Objektvariable nötig ist.

Das folgende Beispiel deklariert in der WiFi-Klasse eine Objektvariable password sowie eine Methode authenticate(String password). Das bedeutet, die Parametervariable heißt genauso wie die Objektvariable. Jeder Zugriff auf password in der Methode bezieht sich auf die Parametervariable und nicht auf die Objektvariable. Der folgende Versuch einer Authentifizierung, in der eigentlich die Parametervariable mit der Objektvariablen verglichen werden soll, ist also semantisch falsch, wobei syntaktisch kein Problem besteht und das Programm immer true ergibt, wenn passwort nicht null ist.

Listing 6.8    src/main/java/com/tutego/insel/oop/WiFi.java

class WiFi {



String password = "+covfefe";

boolean isAuthenticated;



boolean authenticate( String password ) {

return isAuthenticated = password.equals( password ); // semantisch falsch!

}



boolean isAuthenticated() {

return isAuthenticated;

}

}

Das heißt aber nicht, dass auf die Objektvariable nicht mehr zugegriffen werden kann. Die this-Referenz zeigt auf das aktuelle Objekt, und damit ist auch ein Zugriff auf Objekteigenschaften jederzeit möglich:

public boolean authenticate( String password ) {

return isAuthenticated = this.password.equals( password );

}

this für Setter nutzen

Häufiger Einsatzort für das this sind Methoden oder Konstruktoren, die Zustände initialisieren. Gerne nennen Entwickler die Parametervariablen so wie die Exemplarvariablen, um damit eine starke Zugehörigkeit auszudrücken. Schreiben wir also eine Methode setName(String):

class Player {



String name;



void setName( String name ) {

this.name = name;

}

}

Das an setName(String) übergebene Objekt soll die Objektvariable name initialisieren. So greift this.name auf die Objektvariable direkt zu, sodass die Zuweisung this.name = name die Objektvariable mit dem Argument initialisiert.

Klassendiagramm für »Player« mit Setter

Abbildung 6.4    Klassendiagramm für »Player« mit Setter

this für kaskadierte Methoden *

Die append(…)-Methoden bei StringBuilder liefern die this-Referenz, sodass sich Folgendes schreiben lässt:

StringBuilder sb = new StringBuilder();

sb.append( "Android oder iPhone" ).append( '?' );

Jedes append(…) liefert das StringBuilder-Objekt, auf dem es aufgerufen wird – wir können also Methoden kaskadiert anhängen oder es bleiben lassen.

Wir wollen diese Möglichkeit bei einem Zauberer (Klasse Wizard) programmieren, sodass die Methoden name(String) und age(int) Spielername und Alter zuweisen. Beide Methoden liefern ihr eigenes Wizard-Objekt über die this-Referenz zurück:

Listing 6.9    src/main/java/com/tutego/insel/game/v4/Wizard.java, Wizard

class Wizard {



String name = "";

int age;



Wizard name( String name ) { this.name = name; return this; }

String name() { return name; }



Wizard age( int item ) { this.age = item; return this; }

int age() { return age; }



String format() {

return name + " ist " + age;

}

}

Erzeugen wir einen Wizard, und kaskadieren wir einige Methoden:

Listing 6.10    src/main/java/com/tutego/insel/game/v4/Gundalf.java, main()

Wizard gundalf = new Wizard().name( "Gundalf" ).age( 60 );

System.out.println( gundalf.name() ); // Gundalf

System.out.println( gundalf.format() ); // Gundalf ist 60

Der Ausdruck new Wizard() liefert eine Referenz, die wir sofort für den Methodenaufruf nutzen. Da name(String) wiederum eine Objektreferenz vom Typ Wizard liefert, ist dahinter direkt .age(int) möglich. Die Verschachtelung von name("Gundalf").age(60) bewirkt, dass Name und Alter gesetzt werden und der jeweils nächste Methodenaufruf in der Kette über this eine Referenz auf dasselbe Objekt, aber mit verändertem internem Zustand bekommt.

Beispiele dieser Bauart sind in der Java-Bibliothek an einigen Stellen zu finden. Sie werden auch Builder genannt. Sie bestehen in der Regel nur an den schreibenden Methoden.

[»]  Hinweis

Die Methode Wizard name(String) ist mit ihrer Rückgabe praktisch, verstößt aber aus zwei Gründen gegen die JavaBeans-Konvention: Setter dürfen keine Rückgabe haben und müssen immer mit set beginnen. JavaBeans sind also nicht mit dieser kompakten Builder-Schreibweise »kompatibel«.

Sich selbst mit this übergeben

Möchte sich ein Objekt A einem anderen Objekt B mitteilen, damit B das andere Objekt A »kennt«, so funktioniert das gut mit der this-Referenz. Demonstrieren wir das an einem »Ich bin dein Vater«-Beispiel: Die zwei Klassen Luke und Vader repräsentieren zwei Personen, wobei Luke ein Attribut dad für seinen Vater hat:

Listing 6.11    src/main/java/com/tutego/insel/oop/LukeAndVader.java, Teil 1

class Luke {

Vader dad;

}



class Vader {

void revealTruthTo( Luke son ) {

son.dad = this;

}

}

Spannend ist die Methode revealTruthTo(Luke), denn sie setzt beim übergebenen Luke-Objekt das dad-Attribut mit der this-Referenz. Damit kennt Luke seinen Vater, was in folgender Klasse getestet wird:

Listing 6.12    src/main/java/com/tutego/insel/oop/LukeAndVader.java, Teil 2

public class LukeAndVader {

public static void main( String[] args ) {

Luke luke = new Luke();

Vader vader = new Vader();

System.out.println( luke.dad ); // null

vader.revealTruthTo( luke );

System.out.println( luke.dad ); // Vader@15db9742

}

}
[»]  Hinweis

In statischen Methoden steht die this-Referenz nicht zur Verführung, da wir uns in Klassenmethoden nicht auf ein konkretes Objekt beziehen.

 


Ihre Meinung?

Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de

<< zurück
 Zum Rheinwerk-Shop
Zum Rheinwerk-Shop: Java ist auch eine Insel Java ist auch eine Insel

Jetzt Buch bestellen


 Buchempfehlungen
Zum Rheinwerk-Shop: Captain CiaoCiao erobert Java

Captain CiaoCiao erobert Java




Zum Rheinwerk-Shop: Java SE 9 Standard-Bibliothek

Java SE 9 Standard-Bibliothek




Zum Rheinwerk-Shop: Algorithmen in Java

Algorithmen in Java




Zum Rheinwerk-Shop: Objektorientierte Programmierung

Objektorientierte Programmierung




 Lieferung
Versandkostenfrei bestellen in Deutschland, Österreich und in die Schweiz

InfoInfo



 

 


Copyright © Rheinwerk Verlag GmbH 2021

Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das Openbook denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt.

Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.

 

[Rheinwerk Computing]



Rheinwerk Verlag GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, service@rheinwerk-verlag.de



Cookie-Einstellungen ändern