Sie sind auf Seite 1von 53

KLA - Eigene Klassen programmieren

Hinweis:
Diese Druckversion der Lerneinheit stellt aufgrund der Beschaffenheit des Mediums eine im Funktionsumfang stark eingeschränkte Variante des
Lernmaterials dar. Um alle Funktionen, insbesondere Verlinkungen, zusätzliche Dateien, Animationen und Interaktionen, nutzen zu können, benötigen
Sie die On- oder Offlineversion.
Die Inhalte sind urheberrechtlich geschützt.
©2023 Berliner Hochschule für Technik (BHT)

KLA - Eigene Klassen programmieren

Autorin: Dorothea Hubrich

20.07.2023 1 von 53
KLA - Eigene Klassen programmieren

Überblick und Lernziele

In dieser Lerneinheit sollen Sie nun endlich Klassen schreiben, die eigene Attribute,
Konstruktoren und Instanzmethoden definieren. Anwendungen werden dann programmiert,
indem Sie die Möglichkeiten der Objekte Ihrer Klassen nutzen.

Lernziele
Lernziele
Sie kennen den Unterschied zwischen Attributen und lokalen Variablen und können beide
deklarieren.
Sie kennen die Sichtbarkeitsmodifizierer public und private. Sie wissen die Bedeutung
dieser beiden und was die default-Sichtbarkeit ist. Sie setzen die Sichtbarkeitsmodifizierer
ein, um Datenkapselung zu erreichen.
Sie kennen die Aufgabe von Konstruktoren und können sie programmieren.
Sie können Instanzmethoden unter Zugriff auf die Attribute des aktuellen Objektes
programmieren.
Insbesondere wissen Sie, was get- und set-Methoden sind, und warum man die toString-
Methode überschreiben sollte.
Sie wissen, was this ist.

Gliederung der Lerneinheit


Gliederung
1. Die Klasse Girokonto
In diesem Kapitel lernen Sie das Beispiel kennen, das sich durch die gesamte Lerneinheit
ziehen wird.
2. Klasse anlegen
Dieses Kapitel behandelt die Definition der Klasse und ihrer Attribute. Das ist der
wesentliche Schritt, um ein reales Objekt im Computer zu simulieren. Hier wird das Prinzip
der Datenkapselung eingeführt und damit auch der Sichtbarkeitsmodifizierer private.
3. Methoden
Sie ergänzen die Klasse um Instanzmethoden. Insbesondere sind hier die Getter und Setter
für den Zugriff auf die Attribute zu nennen und die Methode toString für eine Ausgabe des
Objekts in der Eingabeaufforderung (Terminal). Sie erlernen den klasseninternen Zugriff
auf die Attribute und lernen this als aktuelles Objekt kennen. Noch einmal sollen Klassen-
und Instanzmethoden gegenübergestellt werden.
4. Konstruktoren
Hier erfahren Sie, wie Konstruktoren angelegt werden und welche Aufgabe der von Ihnen
zu schreibende Code hat.
5. Rasenmäher-Beispiel
An einem zweiten Beispiel soll das Zusammenspiel von Objekten mehrerer verschiedener
Klassen gezeigt werden, die gemeinsam eine Aufgabe erfüllen. Deutlich wird auch, wann
welche Art von Daten im Speicher abgelegt werden und wie lange sie dort bleiben.

Zeitbedarf und Umfang


Zeitbedarf
Für die Bearbeitung dieser Lerneinheit benötigen Sie etwa 120 Minuten. Für die Bearbeitung
aller Übungen insgesamt etwa 120 Minuten (obwohl Musterlösungen bereitstehen, ist es für
den Lernerfolg empfehlenswert, so viele Übungen wie möglich selbstständig zu bearbeiten), für
die Einsendeaufgabe sind zusätzlich 60 Minuten vorgesehen.

Achtung: Aufgrund von unterschiedlichen Vorkenntnissen gibt es in dieser Lerneinheit zum


Teil erhebliche Unterschiede für die benötigte Zeit.

20.07.2023 2 von 53
KLA - Eigene Klassen programmieren

1 Beispiel Girokonto
Objekte modellieren Wie Sie bereits wissen, ist der Grundgedanke der Objektorientierten Programmierung, dass man
versucht, Objekte der realen Welt im Computer zu modellieren. An den Beispielen aus der
Standardbibliothek haben Sie aber auch gesehen, dass Objekte im Computer nicht unbedingt ein
Pendant im realen Leben haben und deshalb manchmal nur schwer vorstellbar sind.

In dieser Lerneinheit soll nun ein Beispiel verwendet werden, das Sie tatsächlich aus dem Alltag
kennen: ein Girokonto. Obwohl die Modellierung sicher nicht vollständig sein wird, können Sie Ihr
Wissen aus der Realität einsetzen, um Entscheidungen über eine geeignete Umsetzung zu
treffen.

Ein großes Programm, das Ihre Klasse verwendet, wird den Umfang dieser Lerneinheit
sprengen. Aber mit ein wenig Vorstellungskraft sollte deutlich werden, dass Ihre Klasse
Grundlage eines Programmes werden könnte, das zum Beispiel in einer Bank eingesetzt wird
oder auch die Accounts in einem Computerspiel verwaltet. Es soll also von Anfang an darauf
geachtet werden, dass Ihre Klasse in verschiedenen Zusammenhängen immer wieder eingesetzt
werden kann.

Da Sie bereits wissen, wie man Objekte verwendet, ist hier ein Programm vorgegeben, das zwei
Girokonten anlegt und Geld von einem zum anderen transferiert. Ziel der Lerneinheit wird es
sein, dieses Programm zum Laufen zu bringen – noch lässt es sich natürlich ohne die neue
Klasse Girokonto noch nicht einmal kompilieren.
KleineBank.java
Rolloverbild 001 /**
002 * ein kleines Bank-Programm
003 *
004 * @author Dorothea Hubrich
005 *
006 */
007 public class KleineBank {
008
009 /**
010 * erstellt zwei Konten und transferiert Geld von einem zum anderen
011 *
012 * @param args
013 */
014 public static void main(String[] args) {
015 Girokonto hansKonto;
016 Girokonto ottosKonto;
hansKonto = new Girokonto("Hans");
017 ottosKonto = new Girokonto("Otto", 1000);
018
019 double hansStand;
020 long hansNr;
021 hansStand = hansKonto.getKontostand();
022 hansNr = hansKonto.getKontonummer();
023
024 System.out.println("Hans hat im Moment " + hansStand
025 + " EUR auf dem Konto mit der Nummer " + hansNr);
026 boolean hatGeklappt;
027 hatGeklappt = ottosKonto.abheben(200);
028 if (hatGeklappt == true) {
029 System.out.println("Die Abhebung war erfolgreich!");
030 double ottosStand;
031 ottosStand = ottosKonto.getKontostand();
032 System.out.println("Neuer Kontostand bei Otto: " + ottosStand);
033 hansKonto.einzahlen(200);
034 }
035 System.out.println("Alle Daten von Hans: " + hansKonto);
036 }
037 }

20.07.2023 3 von 53
KLA - Eigene Klassen programmieren

Textversion: KleineBank.java
Zeilen 001 bis 006
Sie sehen, dass am Beginn des Codes keine import-Anweisung steht. Es werden
keine Klassen aus anderen Paketen benutzt.

Zeilen 015 und 016


Hier werden Variablen deklariert. Girokonto muss also ein Datentyp und damit eine
Klasse sein (siehe Lerneinheit OBJ). Damit diese Zeilen vom Compiler akzeptiert
werden, wird die neue Klasse Girokonto heißen müssen.

Zeilen 017 und 018


Um neue Objekte zu erzeugen, werden die Konstruktoren der Klasse Girokonto
aufgerufen (siehe Lerneinheit OBJ). Offenbar soll es zwei verschiedene geben,
einer mit einem, der andere mit zwei Parametern. Was genau die Parameter
bedeuten sollen, kann man aus dem Programm natürlich nicht sicher schließen, aber
vermuten: Der Name des Kontoinhabers und der anfängliche Kontostand.

Zeilen 021 und 022


Hier werden die ersten Instanzmethoden der neuen Klasse aufgerufen:
getKontostand und getKontonummer (siehe Lerneinheit OBJ). Es handelt sich um
sogenannte Getter, die mithelfen, die im Girokonto gespeicherten Daten zu kapseln
und sicher zu verwalten.

Zeile 027
Auch hier wird eine Instanzmethode der neuen Klasse aufgerufen, die versucht, Geld
vom Girokonto abzuheben. Das kann natürlich schief gehen, weshalb die Methode
einen Rückgabewert vom Typ boolean bekommen soll. Er zeigt an, ob die Abhebung
durchgeführt worden ist oder nicht.

Zeile 028
Hier sehen Sie eine Verzweigung, eine der Kontrollstrukturen, die es in Java gibt.
Sicherlich ist der Aufbau recht selbsterklärend: Hinter dem Schlüsselwort if steht in
runden Klammern eine Bedingung. Ist die Bedingung (ein Ausdruck vom Datentyp
boolean) wahr, wird der Codeblock in den folgenden geschweiften Klammern
ausgeführt, ist sie falsch, wird er einfach übersprungen. In beiden Fällen setzt sich die
Ausführung hinter der schließenden geschweiften Klammer fort. Genauer geht die
Lerneinheit SEQ auf diese if-Anweisung ein.

Zeilen 031 und 033


Noch einmal werden Methoden der Girokonto-Objekte aufgerufen. getKontostand
tauchte oben bereits einmal auf, einzahlen ist eine weitere zu schreibende Methode,
die den genannten Betrag auf das Girokonto einzahlen soll.

Zeile 035
Hier wird das in hansKonto gespeicherte Girokonto-Objekt in der
Eingabeaufforderung (Terminal) ausgegeben. Auch wenn das nicht sichtbar ist,
handelt es sich hierbei ebenfalls um einen Methodenaufruf, und zwar der
vordefinierten Methode toString. Sie werden also selbst festlegen können, wie
genau die Ausgabe eines Girokontos in der Eingabeaufforderung (Terminal) aussieht.

KleineBank.java (951 Bytes)

20.07.2023 4 von 53
KLA - Eigene Klassen programmieren

Übung KLA-01
Multiple Choice
Methodendeklaration
Können Sie aus dem Code erkennen, was wohl zur Methode einzahlen in der
Deklaration stehen sollte?
Richtig Falsch Auswertung
public void einzahlen(double betrag)

public static void einzahlen(double betrag)

public double einzahlen()

public einzahlen()

Eine wichtige Erkenntnis können Sie aus diesem noch nicht funktionsfähigen Code mitnehmen:
Hinweis
„Wenn man für Klassen und Methoden Namen verwendet, die etwas über ihre
Funktionalität aussagen, werden Programme viel leichter verständlich!“
In UML-Notation soll die zu erstellende Klasse später so aussehen:
Girokonto
- inhaber: zeichenkette
- kontonummer: ganzzahlig {readonly}
- kontostand: fließkomma
+ Girokonto(inhaber: zeichenkette)
+ Girokonto(inhaber: zeichenkette, betrag:fließkomma)
+ getKontostand: fließkomma
+ getKontonummer: ganzzahlig
+ getInhaber: zeichenkette
+ einzahlen(betrag: fließkomma)
+ abheben(betrag: fließkomma): wahrheitswert
Abb.: Entwurf der Klasse + toString():String
Girokonto in UML-Notation

Auch wenn Ihnen die Notation nicht vertraut ist, sehen Sie alle Methoden, die eben bereits
aufgerufen worden sind, und darüber hinaus schon Attribute, die die Klasse benötigt, um die
Funktionalität der Methoden sinnvoll zu gewährleisten. Das ist also ein ganz guter Plan zur
Erstellung der Klasse. Im Laufe dieser Lerneinheit werden noch weitere nützliche Methoden
ergänzt werden.

20.07.2023 5 von 53
KLA - Eigene Klassen programmieren

2 Klasse anlegen

Das Anlegen einer Klasse kennen Sie bereits:


Anlegen einer Klasse
/**
Quellcode
* Beschreibung der Klasse
*/
public class Klassenname {
//hier alle Mitglieder der Klasse
}

Dieser Code muss in einer Datei namens Klassenname.java stehen.


Die übliche Namenskonvention besagt, dass Klassennamen mit einem Großbuchstaben
beginnen. Ansonsten gelten alle Regeln für Bezeichner.
Tipp: Verwenden Sie als Klassenbezeichner ein Substantiv in der Einzahl. Begriffe in der
Hinweis
Mehrzahl verwirren eher Sie selbst, weil Sie es als Programmierer immer nur mit einem Objekt
auf einmal zu tun haben.
Der Unterschied zu den Dateien, die Sie bisher geschrieben haben, besteht nur darin, dass es in
dieser Klasse keine main-Methode und auch sonst noch nichts gibt. Aber dass Klassen mehr
oder weniger viele Methoden enthalten können, wissen Sie ja auch bereits.
Für das Beispiel Girokonto lautet der Inhalt der Datei Girokonto.java also so:
Girokonto.java
/**
Quellcode
* Die Objekte dieser Klasse stellen Girokonten bei einer Bank dar.
* Modelliert werden der Inhaber, die Kontonummer und der Kontostand des
* Girokontos. Der Kontostand ist dabei nie negativ.
* @author Dorothea Hubrich
*
*/
public class Girokonto {
}

Es ist wichtig, dass Sie die Datei Girokonto.java im gleichen Ordner speichern wie die Datei
KleineBank.java.
Wegen der von Java geforderten Übereinstimmung zwischen Klassen- und Dateinamen darf es
Hinweis
pro Datei immer nur genau eine public class geben.

Es ist in Java möglich, mehrere Klassen in eine gemeinsame Datei zu schreiben, wenn man das
Schlüsselwort public nur bei einer davon angibt. Bei den anderen fällt es einfach weg. Dadurch
sind sie nicht im gesamten Programm benutzbar, sondern dienen nur als Hilfe, um den Code
besser zu strukturieren.

Grundsätzlich ist es ein eher schlechter Stil, mehrere Klassen in eine Datei zu schreiben, und
wird nicht empfohlen - auch wenn es technisch möglich ist.
Dokumentations-kommentar Sie wissen bereits, dass man jede Methode mit einem Dokumentationskommentar versieht. Das
gleiche gilt natürlich auch für Klassen vor dem eigentlichen Beginn ihres Codes. Versuchen Sie
hier möglichst genau darzulegen, welche Objekte aus der realen Welt Sie modellieren wollen, für
welche Teilaspekte der realen Objekte Sie sich entschieden haben, welche Sie weggelassen
haben.

Neben der Beschreibung der Objekte enthält der Dokumentationskommentar von Klassen oft
folgende Tags:

@author Programmierer dieser Klasse


@version Versionsnummer der Klasse

20.07.2023 6 von 53
KLA - Eigene Klassen programmieren

Im Beispielcode steht hier, dass Konten einer Bank dargestellt werden sollen, dass die
Modellierung aber nur sehr eingeschränkt gegenüber der Realität ist – z. B. haben die Objekte
dieser Girokonto-Klasse keinen Dispo, man kann das Konto also nicht überziehen.

2.1 Impliziter Defaultkonstruktor

Sobald Sie die Klasse Girokonto angelegt haben, können Sie Variablen mit Girokonto als
Datentyp deklarieren. Der Compiler kennt diesen Datentyp jetzt.

Und es geht sogar noch mehr: Sie können nämlich auch schon Objekte der neuen Klasse
erstellen und ausgeben:
Girokonto als Datentyp in KleineBank.java
public static void main(String[] args) {
Quellcode
Girokonto hansKonto;
Girokonto ottosKonto;
hansKonto = new Girokonto();
ottosKonto = new Girokonto();
System.out.println(hansKonto);
System.out.println(ottosKonto);
}
KleineBank.java (1 KB)

Wenn Sie nicht selbst einen Konstruktor schreiben, bietet jede Klasse grundsätzlich einen
Hinweis impliziten Defaultkonstruktor an. Er stellt genügend Speicherplatz für ein Objekt zur Verfügung
und initialisiert alle Attribute der Klasse je nach Typ mit 0 (ganzzahlige Typen), 0.0
(Fließkommatypen), false (boolean) oder null (alle Klassentypen).

Besonders viel zu tun hat der Defaultkonstruktor bisher allerdings nicht, da ein Girokonto noch
keine Attribute hat, die initialisiert werden müssten.

Auch die Ausgabe in der Eingabeaufforderung (Terminal) ist im Moment noch wenig
aussagekräftig:
Girokonto@372f7a8d
Abb.: Ausgabe in der Girokonto@2f92e0f4
Eingabeaufforderung (Terminal)

Wenn Sie für eine Klasse noch keine eigene Ausgabe-Methode (toString) geschrieben haben,
wird die Standard-Implementierung benutzt: Vorne steht der vollständige Klassenname, daran
schließt sich ein sogenannter Hashcode an.

Hier soll nicht erläutert werden, wie genau dieser Hashcode zustande kommt, aber in den
meisten Implementierungen bezieht er die Adresse mit ein, unter welcher die Attribute des
Objektes im Speicher des Computers zu finden sind. Sie können aus dieser Ausgabe also
zumindest schließen, dass der implizite Defaultkonstruktor für beide Objekte unterschiedliche
Speicherplätze reserviert hat und darin notiert hat, dass sie zur Klasse Girokonto gehören.

Im Folgenden soll natürlich auch noch eine eigene sinnvollere toString-Methode


geschrieben werden, um die Ausgabe geeigneter für menschliche Lesende zu gestalten.

20.07.2023 7 von 53
KLA - Eigene Klassen programmieren

2.2 Attribute anlegen

Zuallererst dienen Objekte der Speicherung zusammengehöriger Daten. In Objekten der Klasse
Girokonto soll vermerkt werden,

welche Nummer das Konto hat,


wem es gehört und
wie hoch der Kontostand ist.
Diese Einzelinformationen nennt man Attribute oder auch Eigenschaften, Felder oder
Instanzvariablen der Klasse.

Attribute werden so deklariert:


Attributdeklaration public class Klassenname {
/**
* Bedeutung des Attributs, Einschraenkung der Werte
*/
private Datentyp attributbezeichner;
}

Das Schlüsselwort private ist empfohlen, kann aber weggelassen werden oder durch public
oder protected ersetzt werden, wenn es für das zu lösende Problem sinnvoller ist.

Die Namenskonvention in Java besagt: „Attributbezeichner sollten mit einem kleinen


Hinweis Buchstaben beginnen.“
Die Reihenfolge der Attribute und später Methoden innerhalb der Klasse ist grundsätzlich
beliebig. Es gehört allerdings zum guten Stil, Attribute oben, die Methoden darunter zu
definieren.

In der Klasse Girokonto könnte das also so aussehen:


Attributdeklaration in Girokonto.java
public class Girokonto {
Quellcode
/**
* die Kontonummer
*/
private long kontonummer;
/**
* der Kontostand, nicht negativ
*/
private double kontostand;
/**
* Der Name des Inhabers
*/
private String inhaber;
}

Für jedes Attribut wurde ein Datentyp und ein Bezeichner festgelegt, der möglichst
aussagekräftig gewählt wurde. Im dokumentierenden Kommentar vor jedem Attribut können alle
Erklärungen untergebracht werden, die darüber hinaus noch notwendig sein sollten, z. B. steht
hier noch einmal, dass der Kontostand nie negativ werden darf – eine Bedingung, die mit der
folgenden Programmierung garantiert werden muss.

20.07.2023 8 von 53
KLA - Eigene Klassen programmieren

2.3 Sichtbarkeitsmodifizierer

private, protected und public nennt man Sichtbarkeitsmodifizierer. Sie bestimmen, wo


im Code auf das damit gekennzeichnete Element zugriffen werden darf. Lässt man den
Sichtbarkeitsmodifizierer weg, spricht man von Default-Sichtbarkeit.

Die Bedeutung der Sichtbarkeitsmodifizierer:


Sichtbarkeitsmodifizierer Zugriff
public überall im gesamten Programm erlaubt
protected in allen Klassen im gleichen Paket und in allen erbenden Klassen erlaubt
in allen Klassen im gleichen Paket erlaubt
Tab.: Sichtbarkeits​modifizierer private ausschließlich in der eigenen Klasse erlaubt

Auf die beiden Sichtbarkeiten default (kein Schlüsselwort hinschreiben) und protected
werden die Lerneinheiten PKG, Kap. 3.2 und VRB, Kap 1.1 eingehen, in denen Sie sich mit
Paketen und mit Vererbung beschäftigen.

Sie sehen, dass private nur sehr eingeschränkte Zugriffsmöglichkeiten bietet, die Benutzung
der Attribute ist ausschließlich innerhalb der Klasse Girokonto, also im Code zwischen der
öffnenden und der schließenden geschweiften Klammer der Klasse erlaubt. Insbesondere
bedeutet das, dass man sie in der main-Methode, die hier ja in einer anderen Klasse
untergebracht ist, nicht direkt verwenden kann.

Die Alternative ist die public-Sichtbarkeit. Sie besagt, dass das entsprechend gekennzeichnete
Attribut überall im gesamten Programm verwendet werden darf. Gehen Sie einmal davon aus,
dass der Kontostand als public gekennzeichnet wird:
public Sichtbarkeit
public class Girokonto {
Quellcode
/**
* der Kontostand, nicht negativ
*/
public double kontostand;
...
}

Dann ist das folgende main-Programm mit zwei schreibenden Zugriffen auf das Attribut
kontostand erlaubt:
main-Programm
Girokonto meins = new Girokonto();
Quellcode
meins.kontostand = 1000000000;
Girokonto jemandAnders = new Girokonto();
jemandAnders.kontostand = -123456789;

Sie sehen, wie schnell man dann zum Milliardär werden kann, wie schnell der Kontostand aber
auch im Minus ist. Beide Aktionen sollten bei einem guten Bank-Programm eigentlich nicht
vorkommen dürfen, weshalb Attribute nur in seltenen Ausnahmefällen als public deklariert
werden.

Attribute macht man private, auch wenn die anderen Sichtbarkeitsmodifizierer technisch
Hinweis möglich wären. Man spricht hier von Datenkapselung, d. h. dem „Verstecken“ der
gespeicherten Daten vor unerwünschtem Zugriff im Inneren eines Objektes.

20.07.2023 9 von 53
KLA - Eigene Klassen programmieren

Übung KLA-02
Programmieren Sichtbarkeitsmodifizierer
Probieren Sie den obigen Code in der main-Methode auszuführen:
vorgabe_uebKLA-02.zip (835 Bytes)
einmal mit dem Sichtbarkeitsmodifizierer public vor dem Attribut kontostand
einmal ohne Sichtbarkeitsmodifizierer
einmal mit dem Sichtbarkeitsmodifizierer private.
Wie reagiert jeweils der Compiler?
Lösung (Siehe Anhang)
Bearbeitungszeit: 5 Minuten

20.07.2023 10 von 53
KLA - Eigene Klassen programmieren

3 Methoden programmieren
Getter- und Setter-Methoden Attribute, die man im Hauptprogramm nicht verwenden kann, erscheinen auf den ersten Blick
nicht sehr sinnvoll. Sie wissen aber bereits, dass man Objekte verwendet, indem man ihre
Methoden aufruft. Die Lösung ist also einfach: Man schreibt Methoden, die die Werte der
Attribute an das aufrufende Hauptprogramm liefern oder auch neue Werte in die Attribute
hineinschreiben. Man spricht von Getter- und Setter-Methoden.

Darüber hinaus soll es auch noch Methoden geben, die die Operationen aus der realen Welt im
Programm abbilden. Sie werden ebenfalls mit den Attributen arbeiten.

3.1 Getter-Methoden
3.2 Setter-Methoden
3.3 Weitere Instanzmethoden
3.4 toString
3.5 Statische Methoden und statische Attribute

3.1 Getter-Methoden

Getter (oder auch get-Methoden) haben nur eine einzige Aufgabe: Sie liefern den Wert eines
Attributes zurück und machen es dadurch sichtbar für Code außerhalb der Klasse.

Wenn Sie sich noch einmal das main-Programm ansehen, das am Ende funktionieren soll,
werden Zugriffsmethoden für die Kontonummer und für den Kontostand benötigt. Also wird die
Klasse ergänzt:
getter-Methode für Girokonto
public class Girokonto {
Quellcode
private long kontonummer;
private double kontostand;
private String inhaber;

/**
* @return die Kontonummer
*/
public long getKontonummer() {
return this.kontonummer;
}

/**
* @return aktueller Kontostand
*/
public double getKontostand() {
return this.kontostand;
}
}

Getter sind die ersten Methoden, die Sie für die Klasse schreiben, der Aufbau sollte Ihnen von
den statischen Methoden her bekannt vorkommen:

20.07.2023 11 von 53
KLA - Eigene Klassen programmieren

get-Methoden
Rolloverbild

Textversion: get-Methoden
public
Sichtbarkeitsmodifizierer: Die Methode ist von überallher aufrufbar.

long
Der Rückgabewert hat den Datentyp long.

getKontonummer
Der Name der Methode lautet getKontonummer.

( )
Die Methode erwartet keinen Parameter.

{ }
In den geschweiften Klammern steht der Code, der von der Methode ausgeführt wird.

this.kontonummer
Mit this.attributbezeichner greift man auf das gewünschte Attribut des
aktuellen Objektes zu.

return
return liefert den angegebenen Wert an die aufrufende Stelle zurück.

Laut Namenskonvention beginnt der Name einer Getter-Methode immer mit dem Wörtchen
Hinweis get, dann folgt der Name der Eigenschaft, die sie zurückliefert, beginnend mit einem
Großbuchstaben.

An diesem einfachen Beispiel können Sie schon sehen, wie man im Inneren der Klasse auf die in
den Attributen gespeicherten Werte zugreift:

Attributzugriff im Klasseninneren
Beispiel
this.attributbezeichner

Das führende this. darf weggelassen werden, was aber Verwechslungsgefahr mit
Parametern und lokalen Variablen birgt und deshalb nicht empfohlen wird.

this bezeichnet im Code immer das aktuelle Objekt, von dem die Methode gerade aufgerufen
Hinweis wird.

20.07.2023 12 von 53
KLA - Eigene Klassen programmieren

Wenn im Programm also steht hansKonto.getKontonummer() meint this hansKonto, wenn


dort ottosKonto.getKontonummer() steht, bezeichnet this das Objekt in ottosKonto. So
ist es möglich, den Code ganz allgemein zu schreiben, so dass er später auf jedes Objekt
angewendet werden kann.

Mit dieser Ergänzung der Klasse Girokonto wächst das main-Programm und ist weiterhin
kompilierbar.
main-Programm der Girokonto-Klasse
public static void main(String[] args) {
Quellcode
Girokonto hansKonto;
Girokonto ottosKonto;
hansKonto = new Girokonto();
ottosKonto = new Girokonto();
double hansStand;
hansStand = hansKonto.getKontostand();
long hansNr;
hansNr = hansKonto.getKontonummer();
System.out.println("Hans hat im Moment " + hansStand +
" EUR auf dem Konto mit der Nummer " + hansNr);
}

Übung KLA-03
Programmieren Kontostand und Kontonummer ausgeben
1. Denksportaufgabe: Überlegen Sie zuerst, bevor Sie das Programm laufen
lassen: Wie hoch wird der Kontostand auf Hans‘ Konto wohl sein? Wie wird seine
Kontonummer lauten? Überprüfen Sie Ihre Vorhersage.
2. Geben Sie Kontostand und Kontonummer nun auch noch von ottosKonto aus.
Ergänzen Sie die Klasse Girokonto um einen Getter für den Inhaber.
Geben Sie in main die Inhaber beider Konten aus. Welche Ausgabe erhalten Sie?
vorgabe_uebKLA-03.zip (1,2 KB)
Lösung (Siehe Anhang)
Bearbeitungszeit: 15 Minuten

Selbstverständlich können Sie auch weitere Getter-Methoden schreiben, die nicht einfach nur
den Wert eines Attributs zurückliefern, sondern zuerst eine Berechnung ausführen, in die die
Attribute einfließen. Z. B. könnte die Klasse Girokonto um eine Methode für eine „hübsche“
Formatierung des Kontostandes ergänzt werden:
Weitere Getter-Methode
Quellcode 001 import java.text.NumberFormat;
002
003 public class Girokonto {
004 /* ... */
005 private double kontostand;
006
007 /**
008 * liefert den Kontostand als String fuer die Ausgabe formatiert
009 *
010 * @return Kontostand mit 2 Nachkommastellen und Euro-Zeichen
011 */
012 public String getStandFormatiert() {
013 NumberFormat nf = NumberFormat.getCurrencyInstance();
014 String ausgabetext = nf.format(this.kontostand);
015 return ausgabetext;
016 }
017 /* ... */
018 }

20.07.2023 13 von 53
KLA - Eigene Klassen programmieren

Formatierung NumberFormat-Objekt
von Zahlen
Ein NumberFormat-Objekt (Paket java.text) dient dazu, Zahlen zu formatieren, also z. B. mit
einer gewünschten Anzahl an Nachkommastellen zu schreiben oder ein Tausendertrennzeichen
einzufügen. Es wird analog zu dem DateTimeFormat-Objekt aus der Einsendeaufgabe zu
Lerneinheit OBJ verwendet:

1. Aufruf einer statischen Methode, um ein NumberFormat-Objekt zu erhalten. Einen


öffentlichen Konstruktor hat diese Klasse nicht.
2. Aufruf der Instanzmethode format, um den String mit der formatierten Zahl zu bekommen.

Übung KLA-04
Programmieren Verschiedene Methoden zur Formatierung
Rufen Sie in main für die Ausgabe die Methode getStandFormatiert auf, statt der
bisherigen Methode getKontostand. Achten Sie auf die veränderten Datentypen!
vorgabe_uebKLA-04.zip (1,4 KB)
Frage: Kann die Methode getKontostand dann nicht wieder gelöscht werden? Sie
wird doch im Programm gar nicht verwendet.
Lösung (Siehe Anhang)
Bearbeitungszeit: 5 Minuten

In der „Eingabeaufforderung“ unter Windows wird Ihnen vermutlich aufgrund des


Hinweis Zeichensatzes das Euro-Zeichen nicht angezeigt. Sie können den Zeichensatz mit dem
folgenden Befehl ändern.

chcp 1252

Dieser Zeichensatz kann allerdings einige andere Zeichen nicht mehr darstellen. Ob die hier
angegebene Codepage 1252 oder die normale Codepage 850 besser passt, müssen Sie von
Fall zu Fall entscheiden.

Linux und macOS verwenden im Terminal einen Zeichensatz, in dem das Zeichen enthalten
ist.

20.07.2023 14 von 53
KLA - Eigene Klassen programmieren

3.2 Setter-Methoden

Sicherlich finden Sie es auch etwas unschön, wenn die Attribute beider Konten sich überhaupt
nicht unterscheiden und dann im Inhaber-Attribut auch noch ein Wert wie null steht, der ja „kein
Objekt“ bedeutet und eigentlich einen Fehler anzeigt.

Als Gegenstück zu den Gettern sind also Setter notwendig, die in die Attribute neue Werte
hineinschreiben:
setter-Methode für Girokonto
public class Girokonto {
Quellcode
/* ... */
private String inhaber;

public String getInhaber() {


return this.inhaber;
}

/**
* @param der Name des neuen Inhabers
*/
public void setInhaber(String inhaber) {
boolean inOrdnung = inhaber != null && !inhaber.equals("");
if (inOrdnung == true) {
this.inhaber = inhaber;
}
}
/* ... */
}

Aufgabe des Setters ist es, einen neuen Wert, den er vom aufrufenden Code bekommt, in das
Attribut hineinzuschreiben. Deshalb hat er einen Parameter, in diesem Fall String inhaber.

Frage von Melanie:


Heißt nicht das Attribut inhaber? Und der Parameter heißt jetzt genauso? Gibt das
keine Probleme?

Antwort:
Nein, Sie müssen nur deutlich ausdrücken, was von beiden Sie meinen: Wenn Sie nur
inhaber schreiben, weiß der Compiler, dass Sie den Parameter verwenden wollen.
Wenn Sie this.inhaber schreiben, wird auf das Attribut zugegriffen.

Frage von Markus:


Aber da gab es eine Regel, dass man this. bei den Attributen weglassen darf…

Antwort:
Diese Regel gilt nur, wenn es keine Namensdoppelungen gibt. In dieser Methode ist
die Regel durch den gleichnamigen Parameter außer Kraft gesetzt. Wenn Sie das
vorangestellte this. stört oder Sie durch die gleichen Namen durcheinanderkommen,
denken Sie sich für die Parameter einfach neue Bezeichner aus, z. B. String
neuerInhaber.

Bevor der neue Wert des Parameters wirklich dem Attribut zugewiesen wird, wird erst einmal
geprüft, ob er in Ordnung ist. Der Fehlerwert null sollte ja eigentlich nicht hineingeschrieben
werden. Und auch ein leerer String – also eine Zeichenkette ohne auch nur einen einzigen
Buchstaben – ist als Name unbrauchbar. Geprüft wird das mit der in der Lerneinheit OBJ -
Objekte behandelten equals-Methode.

20.07.2023 15 von 53
KLA - Eigene Klassen programmieren

Hier taucht noch einmal die if-Anweisung auf, die erst einmal testet, ob eine Bedingung erfüllt
ist, und den Code in den geschweiften Klammern nur dann ausführt, wenn diese wahr ist.
Übung KLA-05
Programmieren Setter-Methode
Ergänzen Sie das Programm und sorgen Sie dafür, dass hansKonto auch wirklich
„Hans“ als Inhaber hat und ottosKonto „Otto“.
Können Sie die Methode setInhaber auch mehrfach für ein Girokonto-Objekt
aufrufen?
vorgabe_uebKLA-05.zip (1,5 KB)
Lösung (Siehe Anhang)
Bearbeitungszeit: 5 Minuten

Nun könnte man für die beiden anderen Attribute kontostand und kontonummer natürlich auch
Setter schreiben nach dem gleichen Prinzip:

Laut Namenskonvention beginnt der Name einer Setter-Methode immer mit dem Wörtchen
Hinweis set, dann folgt der Name der Eigenschaft, die sie verändert, beginnend mit einem
Großbuchstaben. Bei zusammengehörenden Gettern und Settern sollte der Name hinter get
bzw. set gleich lauten.

Setter haben keinen Rückgabewert (void), dafür aber einen Parameter für den neuen Wert
des Attributs.

Logisch wären also die Namen setKontostand und setKontonummer. Es bleibt nur die Frage,
ob es diese Methoden überhaupt geben soll:

Die Kontonummer kann in der realen Welt nach der Erstellung eines Kontos nicht mehr
verändert werden. Sie muss also ein einziges Mal im Konstruktor gesetzt werden und bleibt
dann bestehen, solange das Girokonto-Objekt existiert. Eine set-Methode, um die
Kontonummer zu ändern, ist also sinnlos. Bitte haben Sie ein wenig Geduld bis Abschnitt
4.
Der Kontostand wird verändert, indem man Einzahlungen und Abhebungen vornimmt. Den
Kontostand einfach auf einen Wunschbetrag zu setzen, ist in der Realität nicht möglich –
sonst wären wohl alle längst Millionäre… Auch hier modelliert ein Setter nicht die Realität.
Während eine get-Methode für die meisten Attribute eine gute Idee ist (auch hier hängt es vom
Hinweis
Einzelfall ab), sollte man bei der set-Methode immer gut überlegen, ob das Attribut wirklich von
außerhalb des Objektes einen neuen Wert bekommen darf oder nicht. Auf jeden Fall sollte eine
set-Methode prüfen, ob der Parameterwert überhaupt gültig für das Attribut ist.

20.07.2023 16 von 53
KLA - Eigene Klassen programmieren

3.3 Weitere Instanzmethoden

Um den Kontostand zu verändern, benötigt man Methoden, die den Vorgang der Einzahlung und
der Abhebung modellieren. Sie stellen die Operationen dar, die in der Realität auf ein Girokonto-
Objekt angewendet werden.

Die allgemeine Syntax für Instanzmethoden lautet folgendermaßen:


Instanzmethode
/**
Quellcode
* Beschreibung der Aufgabe, die die Methode erfuellt
* @param parameter1 Bedeutung des ersten Parameters
* ...
* @return Beschreibung des Rueckgabewertes
*/
public Datentyp methodenbezeichner
(Datentyp1 parameter1, Datentyp2 parameter2, ...) {
// fuehre Anweisungen aus unter Zugriff auf die Attribute
return wert;
}

Berechnet die Methode kein Ergebnis, wird statt des Datentyps vor dem Bezeichner das Wort
void angegeben und die return - Anweisung fällt weg. Anderenfalls muss der hinter return
angegebene Wert zum oben angekündigten Rückgabedatentyp gehören.
Im Inneren der Methode können Sie mit this.attributname auf die Attribute des aktuellen
Objekts zugreifen.

Statt public sind auch alle anderen Sichtbarkeitsmodfizierer erlaubt.

Zum einen sehen Sie, dass sich Getter und Setter nach genau dieser Syntax richten, für den
Compiler also eigentlich nichts Besonderes sind. Zum anderen sollte Ihnen diese Syntax von den
statischen Methoden her sehr bekannt vorkommen – Sie wissen bereits, was es mit
Parametern und Rückgabewerten auf sich hat.

Methodenüberladung
Hinweis
Selbstverständlich sind auch bei den Instanzmethoden Überladungen erlaubt, also mehrere
Methoden gleichen Namens, die sich in Anzahl und/oder Datentypen der Parameter
unterscheiden.

Mit diesem Wissen sind die Methoden für Einzahlungen und Abhebungen leicht zu formulieren:

20.07.2023 17 von 53
KLA - Eigene Klassen programmieren

Methoden für Einzahlungen und Abhebungen


Rolloverbild 001 public class Girokonto {
002 /* ... */
003 private double kontostand;
004
005 /**
006 * zahlt den Betrag auf this ein
007 *
008 * @param betrag der einzuzahlende Betrag, darf nicht negativ sein
009 */
010 public void einzahlen(double betrag) {
011 if(betrag > 0) {
012 this.kontostand = this.kontostand + betrag;
013 }
014 }
015
016 /**
017 * hebt den gewuenschten Betrag von this ab
018 *
019 * @param betrag der gewuenschte Abhebungsbetrag, darf nicht negativ se
020 in
021 * @return true, wenn die Abhebung moeglich war;
022 * false, wenn das Konto nicht ausreichend gedeckt ist
*/
023 public boolean abheben(double betrag) {
024 boolean kontoGedeckt = this.kontostand >= betrag;
025 if (betrag > 0 && kontoGedeckt) {
026 this.kontostand = this.kontostand - betrag;
027 return true;
028 }
029 return false;
030 }
031 }

Textversion: Methoden für Einzahlungen und Abhebungen


Zeile 010
Hier wird die erste neue Methode definiert. Sie hat einen Parameter – den Betrag, den
man auf das Konto einzahlen möchte – aber keinen Rückgabewert.

Zeile 011
Eine Einzahlung ist nur sinnvoll, wenn der Einzahlungsbetrag positiv ist. Indem Sie
das hier prüfen, verhindern Sie, dass jemand die Methode fälschlicherweise mit einem
negativen Parameter aufruft und dadurch Schaden (in diesem Fall evtl. einen
negativen Kontostand) verursacht.

Zeile 012
Hauptaufgabe der Methode ist es, den Kontostand des aktuellen Objekts zu erhöhen.

Zeile 023
Hier beginnt die zweite neue Methode. Genau wie einzahlen hat sie den
gewünschten Abhebebetrag als Parameter. Da man hier davon ausgehen muss, dass
es schon einmal vorkommt, dass jemand mehr abheben möchte, als auf dem Konto
ist, hat diese Methode einen Rückgabewert. Sie kann dem Aufrufer dadurch
anzeigen, ob die Abhebung erfolgreich war oder nicht.

Zeile 024
Entsprechend wird hier zuerst geprüft, ob der aktuelle Kontostand überhaupt für den
gewünschten Betrag ausreicht.

Zeile 026
Sind die Voraussetzungen für eine Abhebung erfüllt, kann der Kontostand des
aktuellen Objekts verringert werden.

20.07.2023 18 von 53
KLA - Eigene Klassen programmieren

Zeile 027
Die Methode gibt true an den aufrufenden Code zurück, um anzuzeigen, dass die
Abhebung erfolgreich durchgeführt wurde. return beendet die Methode dann sofort.

Zeile 029
Wird diese Anweisung erreicht, waren die Voraussetzungen für die Abhebung nicht
erfüllt. An den aufrufenden Code wird deshalb der Wert false zurückgegeben.

Girokonto.java (745 Bytes)

Attribute ↔ lokale Variablen ↔ Parameter

Diese Begriffe tauchten bisher immer wieder auf. In der Methode abheben kommen auch alle
drei zur Verwendung:
Entfernung aus dem
Deklaration Initialisierung Bedeutung
Speicher
innerhalb der in der Methode, sofort beim Hilfsspeicher für
lokale Variable: Methode bei jedem Methodenende Berechnungen innerhalb
kontoGedeckt Methodenaufruf einer Methode
neu
in den runden beim Aufruf sofort beim Werte, die vom
Parameter: Klammern z.B. in main Methodenende aufrufenden Code zur
betrag einer Methode Steuerung an die Methode
übergeben werden
in der Klasse, im Konstruktor, erst, wenn das Werte, die zusammen das
aber kann aber in Objekt nicht mehr Objekt ausmachen und
Attribut:
this.kontostand außerhalb der den Methoden zugreifbar ist, ggf. über viele Methodenaufrufe
Methode (mit verändert sogar erst zum hinweg bestehen bleiben.
Tab.: Attribute, lokale Variablen
und Parameter private) werden Programmende

Überlegen Sie sich anhand dieser Unterschiede also immer gut, wie lange Sie eine zu
speichernde Information benötigen und wo im Code ihr Wert gesetzt werden soll, und
entscheiden Sie danach, welche Speicherart die Richtige ist.

Mit diesen beiden neuen Methoden sollte das Zielprogramm fast vollständig lauffähig sein:
Neue Methoden
Quellcode 001 public static void main(String[] args) {
002 Girokonto hansKonto;
003 Girokonto ottosKonto;
004 hansKonto = new Girokonto();
005 ottosKonto = new Girokonto();
006 double hansStand;
007 hansStand = hansKonto.getKontostand();
008 long hansNr;
009 hansNr = hansKonto.getKontonummer();
010 System.out.println("Hans hat im Moment " + hansStand
011 + " EUR auf dem Konto mit der Nummer " + hansNr);
012
013 boolean hatGeklappt;
014 hatGeklappt = ottosKonto.abheben(200);
015 if (hatGeklappt == true) {
016 System.out.println("Die Abhebung war erfolgreich!");
017 double ottosStand;
018 ottosStand = ottosKonto.getKontostand();
019 System.out.println("Neuer Kontostand bei Otto: " + ottosStand);
020 hansKonto.einzahlen(200);
021 }
022 }

20.07.2023 19 von 53
KLA - Eigene Klassen programmieren

Übung KLA-06
Programmieren
Girokonto erweitern
vorgabe_uebKLA-06.zip (5 KB)
1. Probieren Sie das Programm aus. Wird die Abhebung durchgeführt?
Ergänzen Sie eine weitere Einzahlung auf ottosKonto, so dass die Abhebung
nun wirklich durchgeführt wird.
Ergänzen Sie mehrere Einzahlungen und Abhebungen auf beiden Konten. Lassen
Sie sich jeweils danach den Kontostand anzeigen. Testen Sie, bis Sie sich sicher
sind, dass die neuen Methoden genauso funktionieren, wie geplant.

2. Ergänzen Sie in Girokonto noch eine Methode


/**
* berechnet die Zinsen gemaess dem uebergebenen Zinssatz und
* addiert sie zum aktuellen Kontostand
* @param zinssatzInProzent ein Wert zwischen 0 und 100
* @return die berechneten Zinsen oder 0, wenn der
* zinssatzInProzent nicht zwischen 0 und 100 liegt.
*/
public double zinsenDazu(double zinssatzInProzent)

Ergänzen Sie auch das Hauptprogramm: Lassen Sie durch den Nutzer oder die
Nutzerin eine Zahl für den Zinssatz eingeben und berechnen Sie die Zinsen, die
Hans bekommt. Geben Sie sowohl die erhaltenen Zinsen, als auch den neuen
Kontostand aus.
3. Ergänzen Sie auch noch diese Methode:
/**
* Ueberweist den angegebenen Betrag von this auf das
* Empfaenger-Konto
* @param betrag Ueberweisungsbetrag
* @param empfaenger Konto des Empfaengers
* @return true, wenn die Ueberweisung ausgefuehrt werden konnte,
* false, wenn nicht.
*/
public boolean ueberweisen(double betrag, Girokonto empfaenger)

Tipp: Eine Überweisung wird ausgeführt, indem von this Geld abgehoben, auf
dem Empfänger-Konto Geld eingezahlt wird. Rufen Sie auch diese Methode im
KleineBank-Programm auf und überweisen Sie Geld von Hans an Otto.
Lösung (Siehe Anhang)
Bearbeitungszeit: 45 Minuten

20.07.2023 20 von 53
KLA - Eigene Klassen programmieren

3.4 toString
Vererbung Eine der am häufigsten implementierten Methoden ist die Ausgabe-Methode toString. Sie
wissen bereits, dass Klassen aufeinander aufbauen, dass also Klassen Methoden anderer
Klassen einfach übernehmen können. Man spricht hier von Vererbung (inheritance), auf die die
Lerneinheit VRB genau eingeht.

Grundsätzlich erben alle Klassen von der Klasse Object, also auch die, die Sie selbst
programmieren. Außer den von Ihnen selbst geschriebenen Methoden verfügt Ihre Klasse damit
automatisch über alle Methoden, die es bereits in Object gibt, insbesondere gilt das für die
Methode toString:

toString-Methode
Definition
Die toString-Methode einer Klasse liefert als Rückgabewert (return value) eine String-
Repräsentation des aktuellen Objekts dieser Klasse zurück. Mit anderen Worten die toString-
Methode wird genutzt, um den Inhalt des aktuellen Objekts (Inhalt der Attribute) in einer für den
Menschen lesbaren Form zurückzugeben.

Da diese spezielle Methode durch den Automatismus der Vererbung nun in wirklich jedem Objekt
jeder beliebigen Klasse vorhanden ist, konnten die Java-Entwickler und Entwicklerinnen die
bekannte Ausgabemethode System.out.println so aufbauen, dass Sie beim Aufruf nur noch
Ihr Objekt in die Klammern schreiben. System.out.println ruft intern die Methode toString
für das Objekt auf, um seine Ausgabedarstellung zu erhalten und diese dann in die
Eingabeaufforderung (Terminal) zu schreiben.
Übung KLA-07
Programmieren System.out.println
Rufen Sie im main-Programm einmal folgendes auf:
System.out.println(hansKonto);
und
System.out.println(hansKonto.toString());

Was stellen Sie fest?


vorgabe_uebKLA-07.zip (6,1 KB)
Lösungshinweis (Siehe Anhang)
Bearbeitungszeit: 2 Minuten

Um nun eine „schöne“ und vor allem für die menschlichen Nutzenden Ihres Programmes
sinnvolle Ausgabe zu erzeugen, sollten Sie selbst eine toString - Methode in der Klasse
Girokonto schreiben:
Eigene toString-Methode
public class Girokonto {
Quellcode
/* ... */

@Override
public String toString() {
String ausgabe;
ausgabe = "Auf dem Girokonto " + this.kontonummer + " von "
+ this.inhaber
+ " sind " + this.getStandFormatiert() + ".";
return ausgabe;
}
}

20.07.2023 21 von 53
KLA - Eigene Klassen programmieren

Die toString-Methode hat als Rückgabewert einen String, also eine Zeichenkette, der alle
interessierenden Attribute des Objektes enthält. Wie genau Sie diese Zeichenkette aufbauen,
bleibt Ihnen als Programmierer der Klasse überlassen. Hier z. B. wurden Texte hinzugefügt und
der Kontostand nicht als einfache Zahl, sondern bereits formatiert in den Ausgabetext
aufgenommen.
Achten Sie bei der Implementierung genau auf die Signatur der Methode toString. Wenn Sie
Hinweis auch nur ein wenig abweichen, funktioniert der Automatismus in System.out.println nicht
mehr.
Im Inneren einer Klasse können die Methoden des aktuellen Objektes mit:
this.methodenname(parameterwert1, parameterwert2,…)
aufgerufen werden

Frage von Melanie:


Warum steht denn da @Override statt eines Dokumentationskommentars?

Antwort:
Da die Methode toString bereits vorhanden ist und in der Klasse Object ausführlich
beschrieben wird, ist ein weiterer Dokumentationskommentar nicht unbedingt
notwendig. Wenn man eine geerbte Methode neu schreibt, spricht man von
überschreiben, deshalb die Annotation @Override. Sie bewirkt, dass der Compiler
aufpasst, dass Sie auch wirklich eine vorhandene Methode überschreiben.
Wenn Sie sich jetzt z. B. beim Methodennamen vertippen, wird er eine Fehlermeldung
ausgeben. Ohne diese Annotation bemerken Sie den Fehler nicht, die Ausgabe klappt
nur nicht wie gewünscht. Eine längere Fehlersuche dürfte die Folge sein…

Übung KLA-08
Programmieren
toString
1. Rufen Sie das main-Programm noch einmal auf. Sehen Sie, dass der neue Code
in der toString-Methode zum Einsatz kommt?
2. „Vertippen“ Sie sich einmal bei toString, schreiben Sie z. B. den Buchstaben s
klein. Wie reagiert der Compiler jetzt?
vorgabe_uebKLA-08.zip (6,1 KB)
Lösung (Siehe Anhang)
Bearbeitungszeit: 4 Minuten

20.07.2023 22 von 53
KLA - Eigene Klassen programmieren

3.5 Statische Methoden und statische Attribute

Bisher war die Kontonummer aller erzeugten Girokonto-Objekte immer 0. Das soll sich nun
endlich ändern. Die entscheidende Frage ist zuerst einmal:

Denksportaufgabe Woher bekommt man eine immer neue Kontonummer, die noch nicht irgendwo vergeben
worden ist?

Sicherlich sind Sie auch auf die Idee gekommen, dass man sich irgendwo merken/speichern
muss, welche Kontonummern bereits vergeben worden sind. Genau genommen reicht es, wenn
man sich die größte bereits vergebene Kontonummer merkt. Indem man 1 addiert, erhält man
dann ganz sicher eine neue Kontonummer, die noch keinem Girokonto-Objekt zugeordnet
worden ist.

Es wird also ein Speicherplatz benötigt, der unabhängig von den einzelnen Objekten ist.
Schließlich hat nicht jedes Girokonto seine eigene „größte bisher vergebene Kontonummer“,
sondern es darf diese Information nur ein einziges Mal im gesamten Programm geben.

Die Lösung ist ein statisches Attribut (auch Klassenvariable genannt) in der Klasse Girokonto:
Klassenvariable
public class Girokonto {
Quellcode
/**
* die groesste bisher vergebene Kontonummer aller Girokonto-Objekte im
* Programm
*/
private static long groessteNummer = 0;
/* ... */
}

Sie erinnern sich hoffentlich noch an die statischen Konstanten, die in Lerneinheit STA - Kap. 4.1
angelegt worden sind. Genau wie die Konstanten wird die Klassenvariable mit dem
Schlüsselwort static gekennzeichnet und existiert dadurch nur ein einziges Mal im gesamten
Programm.

Abb.: Aufbau der Methode printIn

Wie bei allen Attributen wird auch hier der Sichtbarkeitsmodifizierer private verwendet, damit
nur der Code innerhalb der Klasse das statische Attribut verwenden und vor allem verändern
darf. Die ganze Verwaltung der Kontonummern würde nicht funktionieren, wenn einfach
irgendwo im Code ein neuer Wert in die Klassenvariable geschrieben werden dürfte.

20.07.2023 23 von 53
KLA - Eigene Klassen programmieren

Statische Attribute bzw. Klassenvariablen bilden eine Art globale Variablen, die nur einmal im
Hinweis gesamten Programm existieren. Auch hier sollte man auf Datenkapselung achten, damit keine
unerwünschten Änderungen daran vorgenommen werden.

Entsprechend braucht man auch hier Methoden, um die Klassenvariable verwenden zu können.
Das könnte natürlich wieder ein Getter sein. Viel interessanter ist aber eine Methode, die gleich
eine neue Kontonummer erzeugt:
Methode für eine neue Kontonummer
Rolloverbild 001 public class Girokonto {
002 /**
003 * die groesste bisher vergebene Kontonummer aller Girokonto-Objekte im
004 * Programm
005 */
006 private static long groessteNummer = 0;
007
008 /**
009 * liefert eine neue noch nicht vergebene Kontonummer
010 * und merkt sich, dass diese nun verwendet wird
011 * @return neue Kontonummer
012 */
013 public static long holeNeueNummer(){
014 Girokonto.groessteNummer++;
015 return Girokonto.groessteNummer;
016 }
017 /* ... */
018 }

Textversion: Methode für eine neue Kontonummer


Zeile 013
Hier wird eine statische Methode definiert, erkennbar am Schlüsselwort static.
Diese Methode soll unabhängig von einem bereits erzeugten Girokonto-Objekt
aufgerufen werden können.

Zeile 014
Auf das statische Attribut greifen Sie mit Hilfe des Klassennamens zu, wie in
Lerneinheit STA gesehen, nicht mit this. (Innerhalb der Klasse wäre es möglich,
den Klassennamen wegzulassen). Die größte bisher vergebene Kontonummer wird
um 1 erhöht, um sicher eine neue Nummer zu erzeugen.

Zeile 015
Dann wird die neu erzeugte Nummer per return an den Aufrufer zurückgegeben.

Übung KLA-09
Multiple Choice
Aufruf der neuen Methode
Machen Sie sich klar, wie man diese neue Methode z. B. in main aufrufen kann:
Richtig Falsch Auswertung
holeNeueNummer(long neu);

long neu = holeNeueNummer();

long neu = Girokonto.holeNeueNummer();

Girokonto meins(holeNeueNummer);

20.07.2023 24 von 53
KLA - Eigene Klassen programmieren

Übung KLA-10
Programmieren
Zugriff von einer statischen Methode
Was passiert, wenn Sie den Code der Methode folgendermaßen abändern?
public static long holeNeueNummer(){
Girokonto.groessteNummer++;
this.kontonummer = Girokonto.groessteNummer;
return Girokonto.groessteNummer;
}

vorgabe_uebKLA-10.zip (6,2 KB)


Lösung (Siehe Anhang)
Bearbeitungszeit: 5 Minuten

Im Unterschied zu Instanzmethoden haben statische Methoden keinen Zugriff auf this und die
Hinweis im aktuellen Objekt gespeicherten Attribute!

Umgekehrt sollten alle Methoden, die überhaupt nicht mit this und seinen Attributen arbeiten,
als static gekennzeichnet werden.

Die neu erzeugte Nummer gleich in das Attribut kontonummer zu schreiben, ist also nicht
möglich. Der nächste Abschnitt bringt mit den selbst geschriebenen Konstruktoren die Lösung.

Frage von Markus:


Wenn ich das Programm mehrmals starte, bekomme ich immer die angeblich neuen
Nummern 1 und 2. Was soll das denn?

Antwort:
Statische Attribute behalten ihren Wert nicht über das Programmende hinaus. Dazu
wären externe Speichertechniken notwendig, wie z. B. der Zugriff auf eine Textdatei
oder eine Datenbank. Damit beschäftigt sich dieser Kurs nicht. Die größte bisher
erzeugte Kontonummer gilt also immer nur für einen einzigen Programmablauf.

20.07.2023 25 von 53
KLA - Eigene Klassen programmieren

4 Konstruktoren

Konstruktoren haben grundsätzlich zwei Aufgaben:

ausreichend Speicherplatz für ein Objekt der Klasse bereitzustellen,


in alle Attribute sinnvolle Initialisierungswerte hineinzuschreiben.
Um den Speicherplatz müssen Sie sich glücklicherweise nicht kümmern, das macht die
Laufzeitumgebung ganz automatisch. Aber was „sinnvolle“ Werte für die Attribute sind, können
nur Sie als Entwickler der Klasse festlegen. Besonders erfolgreich war der implizite
Defaultkonstruktor da ja nicht gerade - der hatte immer 0 als Kontonummer und einen nicht
vorhandenen Inhabernamen festgelegt…

Ein Konstruktor für die Klasse Girokonto kann so aussehen:


Konstruktor der Klasse Girokonto
Rolloverbild 001 public class Girokonto {
002 private long kontonummer;
003 private double kontostand;
004 private String inhaber;
005
006 /**
007 * dieser Konstruktor erstellt ein Standardkonto
008 * mit einem Anfangskontostand von 0 und einem
009 * unbekannten Kontoinhaber
010 */
011 public Girokonto() {
012 this.inhaber = "unbekannt";
013 this.kontostand = 0.0;
014 this.kontonummer = Girokonto.holeNeueNummer();
015 }
016 /* ... */
017 }

Textversion: Konstruktor der Klasse Girokonto


Zeile 011
Ein Konstruktor ist eine sehr spezielle Methode. Er heißt immer genauso wie die
Klasse, hier also Girokonto. Im Gegensatz zu normalen Methoden kündigt er keinen
Rückgabewert an, auch das sonst übliche void fehlt. Der hier gezeigte Konstruktor
hat keine Parameter, die runden Klammern bleiben also leer. Es handelt sich also um
einen Standardkonstruktor.

Zeile 012
Aufgabe des Konstruktors ist es, in alle Attribute des neu zu erstellenden Objektes
sinnvolle Initialisierungswerte hineinzuschreiben. Hier bekommt also das Attribut
inhaber einen Wert.

Zeile 013
Ebenso wird dem Attribut kontostand ein Anfangswert zugewiesen.

Zeile 014
Auch das Attribut kontonummer bekommt einen Wert. Dieser wird nicht einfach
festgelegt, sondern erst durch einen Methodenaufruf berechnet. Wie gut, dass die
statische Methode zur Erzeugung einer immer neuen Kontonummer bereits
vorhanden ist.

20.07.2023 26 von 53
KLA - Eigene Klassen programmieren

Standardwerte Sollten Sie in einem Konstruktor die Zuweisung an ein Attribut weglassen, erhält es den
Standardwert, den auch der implizite Default-Konstruktor vergeben würde (0, 0.0, false oder
null). In diesem Beispiel könnte man theoretisch also die Zuweisung des Kontostandes
einsparen. Leider wird das Programm dadurch wieder schwerer verständlich, so dass das nicht
empfehlenswert ist.
Übung KLA-11
Programmieren Unterschiedliche Kontonummern
Lassen Sie das Programm KleineBank noch einmal laufen. Sehen Sie, dass die
Konten jetzt unterschiedliche Kontonummern haben?
vorgabe_uebKLA-11.zip (4,5 KB)
Bearbeitungszeit: 2 Minuten

Der selbst geschriebene Konstruktor mit den eigenen Zuweisungen an die Attribute hat also den
impliziten Defaultkonstruktor ersetzt.

Defaultkonstruktor
Definition
Grundsätzlich steht der implizite Defaultkonstruktor nur zur Verfügung, solange eine Klasse
keinen selbst geschriebenen Konstruktor hat. Das gilt auch dann, wenn dieser selbst
geschriebene Konstruktor Parameter hat, also Argumente in den runden Klammern erwartet.

Direkte Initialisierung der Attribute

Java erlaubt eine andere Form der Initialisierung von Attributen, nämlich direkt bei ihrer
Deklaration. Man könnte den eben gezeigten Standardkonstruktor auch ersetzen durch:
Direkte Initialisierung der Attribute
public class Girokonto {
Quellcode
private long kontonummer = Girokonto.holeNeueNummer();
private double kontostand = 0.0;
private String inhaber = "unbekannt";
/* ... */
}

Die hier angegebenen Werte werden dann vom impliziten Standardkonstruktor verwendet bzw.
genutzt, falls Sie in einem selbst geschriebenen Konstruktor die Initialisierung eines Attributes
unterlassen haben.

Grundsätzlich sind beide Varianten – einen expliziten Konstruktor schreiben oder die
Initialisierungswerte direkt bei der Deklaration angeben – weit verbreitet. Welche man benutzt, ist
eine Frage des persönlichen Stils. Vermeiden sollte man nur einen Mix aus beiden.

Da die Methode Girokonto.holeNeueNummer tatsächlich ausschließlich von den


Hinweis Konstruktoren verwendet werden soll – das Hauptprogramm braucht schließlich keine neuen
Kontonummern, ohne auch ein neues Konto zu erstellen – kann hier der
Sichtbarkeitsmodifizierer private statt public verwendet werden. Ein Zugriff in main ist dann
natürlich nicht mehr möglich.

20.07.2023 27 von 53
KLA - Eigene Klassen programmieren

4.1 Konstruktoren mit Parametern

Allgemein lautet die Syntax für die Definition eines Konstruktors so:
Syntax für die Definition eines Konstruktors
/**
* Beschreibung des zu erstellenden Objekts
* @param parameter1 Bedeutung des ersten Parameters
* ...
*/
public Klassenname(Datentyp1 parameter1, Datentyp2 parameter2, ...) {
// rufe evtl. einen anderen Konstruktor auf
// weise allen Attributen Iniatialisierungswerte zu
}

Ein Konstruktor kann also Parameter haben, d. h. er bekommt Werte von der Aufrufstelle, die in
die Initialisierung der Attribute einfließen sollen. In unserem Beispiel ist es sicherlich sinnvoll,
wenn man gleich zu Beginn festlegen kann, wem das Konto eigentlich gehört.

Überladen von Konstruktoren


Hinweis
Konstruktoren können, wie Methoden auch, überladen werden. Eine Klasse kann also beliebig
viele Konstruktoren haben, wenn sie unterschiedliche Parameterlisten haben.

Konstruktor mit Parameter


public class Girokonto {
Quellcode
/* ... */
/**
* Dieser Konstruktor erstellt ein leeres Konto
* fuer den angegebenen Inhaber
* @param inhaber der neue Kontoinhaber
*/
public Girokonto(String inhaber) {
this.inhaber = "unbekannt";
boolean inOrdnung = inhaber != null && !inhaber.equals("");
if(inOrdnung == true) {
this.inhaber = inhaber;
}
this.kontostand = 0.0;
this.kontonummer = Girokonto.holeNeueNummer();
}
/* ... */
}

Dieser neue Konstruktor erwartet, dass beim Aufruf in den Klammern der Name des zukünftigen
Kontoinhabers angegeben wird. Der Aufrufer hat damit die Möglichkeit, den Initialisierungswert
für dieses Attribut selbst zu bestimmen.

Gleichzeitig sichert die Programmierung wieder ab, dass dieser von außen in die Klasse
hineingegebene Wert auch gültig ist. null wird hier nicht akzeptiert und eine Zeichenkette ganz
ohne Buchstaben auch nicht. Die gleiche Prüfung war in der set-Methode für den Inhaber
eingebaut. Sollte die Prüfung nicht positiv sein, sorgt der Konstruktor dafür, dass „unbekannt“ als
Inhaber eingetragen wird. In der Lerneinheit „EXC - Ausnahmen“ erfahren Sie, wie man die
Erzeugung eines neuen Objektes komplett verhindern kann, wenn versucht wird, ungültige Werte
in die Attribute zu schreiben.

Der Parameter heißt hier genauso wie das Attribut, für das er den Wert vom aufrufenden
Programm enthält. Das ist durchaus üblich. Für den Rechner sind beide klar unterschieden, weil
das Attribut inhaber mit führendem this. geschrieben wird, der Parameter inhaber ohne.
Wenn Sie diese Namensdoppelung durcheinanderbringt, können Sie den Parameter gerne
anders benennen.

Mit diesem neuen Konstruktor ist nun noch eine weitere Zeile des von Beginn an geplanten
Programmes möglich:

20.07.2023 28 von 53
KLA - Eigene Klassen programmieren

Aufruf des Konstruktors


public static void main(String[] args) {
Quellcode
Girokonto hansKonto;
Girokonto ottosKonto;
hansKonto = new Girokonto("Hans");
//Achtung: setInhaber wird nicht aufgerufen!
ottosKonto = new Girokonto();
/* ... */
}

Übung KLA-12
Programmieren
Konstruktor für den Anfangsbestand
Lassen Sie das KleineBank-Programm noch einmal laufen. Sie sollten jetzt den – von
Beginn an – eingetragenen Kontoinhaber Hans sehen.
Ergänzen Sie noch einen weiteren Konstruktor:
public Girokonto(String inhaber, double anfangsstand)

Er soll ein Konto erzeugen, das dem angegebenen Inhaber gehört und gleich zu
Beginn den angegebenen Kontostand hat, wenn dieser nicht negativ ist.
Rufen Sie diesen neuen Konstruktor in KleineBank für ottosKonto auf: Das
Girokonto sollte „Otto“ gehören und sofort mit 1000€ gefüllt sein.
vorgabe_uebKLA-12.zip (4,5 KB)
Lösung (Siehe Anhang)
Bearbeitungszeit: 5 Minuten

20.07.2023 29 von 53
KLA - Eigene Klassen programmieren

4.2 Aufruf vorhandener Konstruktoren

Inzwischen hat die Klasse Girokonto drei Konstruktoren. Das ist nicht schlimm – im Gegenteil.
Es ist allerdings nicht sinnvoll, dass der Code in den Konstruktoren mehrfach dort steht. Vielleicht
haben Sie sogar „Copy & Paste“ benutzt.
Ganz generell gilt: Vermeiden Sie Code-Verdoppelung. Meist gibt es einen anderen Weg.
Hinweis
Code-Verdoppelung
Rolloverbild 001 public class Girokonto {
002
003 public Girokonto() {
004 this.inhaber = "unbekannt";
005 this.kontostand = 0.0;
006 this.kontonummer = Girokonto.holeNeueNummer();
007 }
008
009 public Girokonto(String inhaber) {
010 this.inhaber = "unbekannt";
011 boolean inOrdnung = inhaber != null && !inhaber.equals("");
012 if (inOrdnung == true) {
013 this.inhaber = inhaber;
014 }
015 this.kontostand = 0.0;
016 this.kontonummer = Girokonto.holeNeueNummer();
017 }
018
019 public Girokonto(String inhaber, double anfangsstand) {
020 this.inhaber = "unbekannt";
021 boolean inOrdnung = inhaber != null && !inhaber.equals("");
022 if (inOrdnung == true) {
023 this.inhaber = inhaber;
024 }
025 this.kontostand = 0.0;
026 if (anfangsstand >= 0) {
027 this.kontostand = anfangsstand;
028 }
029 this.kontonummer = Girokonto.holeNeueNummer();
030 }
031 /* ... */
032 }

Textversion: Code-Verdoppelung
Zeile 006:
Diese Zeile kommt in jedem Konstruktor vor (siehe auch Zeilen 016 und 029).

Zeilen 010 - 014:


Dieser Teil ist auch doppelt (siehe auch Zeilen 020 bis 024).

Zeile 016:
Diese Zeile kommt in jedem Konstruktor vor (siehe auch Zeilen 006 und 029).

Zeilen 020 - 024:


Dieser Teil ist auch doppelt (siehe auch Zeilen 010 bis 014).

Zeile 029:
Diese Zeile kommt in jedem Konstruktor vor (siehe auch Zeilen 006 und 016).

Der letzte Konstruktor ist der ausführlichste von den dreien. Er setzt die Attribute inhaber und
kontostand auf Wunschwerte von der Aufrufstelle und erzeugt eine neue Kontonummer mit
Hilfe der statischen Methode.

20.07.2023 30 von 53
KLA - Eigene Klassen programmieren

Nun kann man das Ganze so betrachten: der erste Konstruktor „wünscht sich“ die Zeichenkette
„unbekannt“ im Attribut inhaber und den Wert 0.0 für kontostand.
Er kann also, statt die Zuweisungen selbst vorzunehmen, den dritten Konstruktor mit seinen
Wunschwerten als Parameter aufrufen. Insgesamt sieht das so aus:
Konstruktor ruft Konstruktor auf
Rolloverbild 001 public class Girokonto {
002 public Girokonto() {
003 this("unbekannt", 0.0);
004 }
005
006 public Girokonto(String inhaber, double anfangsstand) {
007 this.inhaber = "unbekannt";
008 boolean inOrdnung = inhaber != null && !inhaber.equals("");
009 if (inOrdnung == true) {
010 this.inhaber = inhaber;
011 }
012 this.kontostand = 0.0;
013 if (anfangsstand >= 0) {
014 this.kontostand = anfangsstand;
015 }
016 this.kontonummer = Girokonto.holeNeueNummer();
017 }
018 /* ... */
019 }

Textversion: Konstruktor ruft Konstruktor auf


Zeile 003:
Die Werte, die in die Attribute inhaber und kontostand sollen, werden an den
dritten Konstruktor übergeben (siehe Zeile 006).

Ein Konstruktor kann sich eigene Zuweisungen sparen, indem er einen anderen Konstruktor
aufruft, die Arbeit also delegiert. Welcher andere Konstruktor gemeint ist, erkennt der Compiler
an Anzahl und Datentypen der Werte in den runden Klammern hinter this. In diesem Fall steht
dort ein String und ein double-Wert. Es kann also nur der dritte Konstruktor gemeint sein, der
genau diese Kombination an Parametern erwartet.

Achtung:
Hinweis
this mit einem folgenden Punkt ist ein Zugriff auf ein Attribut oder eine Methode.
this mit folgenden runden Klammern ist die Weitergabe eines Konstruktoraufrufs an einen
anderen und ist ausschließlich innerhalb eines Konstruktors erlaubt!

Allgemein lautet die Syntax des expliziten Konstruktoraufrufs folgendermaßen:


Syntax des expliziten Konstruktoraufrufs
001 public class Klassenname {
002 public Klassenname(Datentyp1 parameter1, Datentyp2 parameter2) {
003 this(wert1, wert2, wert3, ...);
004 //weitere Anweisungen
005 }
006 /* ... */
007 }

Die Klasse muss einen weiteren Konstruktor haben, dessen Signatur zu den in Klammern hinter
this angegebenen Werten passt.

Vor dem expliziten Aufruf mit this(…) dürfen keine Anweisungen stehen.

20.07.2023 31 von 53
KLA - Eigene Klassen programmieren

Übung KLA-13
Programmieren
Konstruktor ruft Konstruktor auf
Ersetzen Sie auch den Code des zweiten Konstruktors durch einen expliziten Aufruf
des dritten Konstruktors.
Probieren Sie aus, was passiert, wenn Sie gegen die obige Syntaxregel verstoßen:
Schreiben Sie z. B. eine Ausgabe-Anweisung vor den expliziten Konstruktoraufruf.

vorgabe_uebKLA-13.zip (4,4 KB)


Lösung (Siehe Anhang)
Bearbeitungszeit: 10 Minuten

4.3 Finale Attribute

Um die Girokonto-Klasse abzuschließen, soll noch eine letzte Änderung daran vorgenommen
werden. Wie Ihnen sicherlich klar ist, ändert sich die Kontonummer eines Girokontos nicht,
solange es existiert. Diese Tatsache aus der realen Welt kann man im Programm abbilden,
indem man das Attribut kontonummer als final kennzeichnet.
Finales Attribut
Quellcode
001 public class Girokonto {
002 /**
003 * die Kontonummer
004 */
005 private final long kontonummer;
006 /* ... */
007 }

Das Schlüsselwort final bedeutet, dass diesem Attribut nur genau einmal ein Wert zugewiesen
werden darf:

Entweder durch direkte Initialisierung bei der Deklaration des Attributs


oder durch eine einzige Zuweisung im Konstruktor.
Eine zweite Zuweisung und damit eine eventuelle Veränderung des einmal gespeicherten
Wertes verhindert der Compiler.

Bedenken Sie, dass die Laufzeitumgebung im Konstruktor allen Attributen einen Standardwert
zuweist, auch dann, wenn Sie diese Anweisung nicht selbst hinschreiben. Außerhalb des
Konstruktors ist eine Zuweisung an ein Attribut also niemals die allererste.
Übung KLA-14
Programmieren
Finales Attribut prüfen
Probieren Sie es aus: Ergänzen Sie in einer beliebigen Methode die Zuweisung
this.kontonummer = 99999;

Wie reagiert der Compiler?


Vorgabe:
Girokonto.java (4,7 KB)

Lösung (Siehe Anhang)


Bearbeitungszeit: 10 Minuten

Sie kennen dieses Verhalten und auch das Schlüsselwort final bereits von den statischen
Konstanten. Während es statische Konstanten aber nur ein einziges Mal im gesamten Programm
gibt, der gespeicherte Wert also wirklich programmweit fest ist, existieren finale Attribute in
jedem einzelnen Objekt. Üblicherweise speichert dann auch jedes Objekt seinen eigenen nicht
veränderlichen Wert, wie hier die Kontonummer.

20.07.2023 32 von 53
KLA - Eigene Klassen programmieren

5 Beispiel Rasenmäher

In diesem Abschnitt soll ein vollkommen anderes komplexes Beispiel behandelt werden, in dem
Sie die bekannten Sachverhalte wiederfinden und Ihr Wissen vertiefen können. Es handelt sich
um eine einfache Aufgabenstellung:

Ein Java-Programm zur Ermittlung der Zeit, die man zum


Rasenmähen benötigt, ist zu entwickeln und zu implementieren.

Gehen Sie wie in den folgenden Schritten vor, um sich das


Beispiel zu erarbeiten:

1. Lesen Sie die Problemstellung.


2. Schauen Sie sich den Entwurf der Klassen in UML-Notation an.
3. Inspizieren Sie den Quellcode. Erfassen Sie, um welche Art von Variablen es sich handelt,
analysieren Sie die Methoden hinsichtlich Parameter und Rückgabewert.
4. In der Diashow wird das Programm in 88 Einzelbildern, die Sie separat anwählen können,
anweisungsweise visualisiert. Nehmen Sie sich viel Zeit, um genau zu erfassen, wann der
Speicherplatz angefordert wird, in welcher Reihenfolge die Methoden aufgerufen werden,
wie die Parameterübergabe erfolgt. Mit den Pfeiltasten bewegen Sie sich szenenweise
vorwärts und rückwärts.

Problembeschreibung

Ein rechteckiges Haus wurde auf einem


rechteckigen Grundstück errichtet. Nun soll
mittels eines Programmes die Zeit, die benötigt
wird, um den Rasen rund um das Gebäude zu
mähen, berechnet und anzeigt werden. Die
Geschwindigkeit beim Mähen ist mit zwei
Quadratmetern pro Minute vorgegeben.

UML-Darstellung

20.07.2023 33 von 53
KLA - Eigene Klassen programmieren

TimeToMow Mowing
+RATE: double

+main(args: String) +Mowing(h: Rectangle, b: Rectangle)


+generateMowingTime() +calculateMowingTime(): double

-house -block

Rectangle
-width: double
-length: double
+Rectangle(l: double, w: double)
+Rectangle(lw: double)
getLength(): double
getWidth(): double
calculateArea(): double
+calculatePerimeter(): double

Abb.: Entwurf der Klassen in


UML-Notation

Diashow
Rasenmäher

© Ainslie Ellis, School of Network Computing, Monash University, Ainslie.Ellis@infotech.monash.edu.au

Rasenmaeher.zip (3,9 KB)

20.07.2023 34 von 53
KLA - Eigene Klassen programmieren

In diesem Beispiel ist deutlich zu sehen, dass mehrere Klassen zusammenarbeiten, um ein
Problem zu lösen. Auch ist die Klasse Rectangle nicht speziell für diesen Einsatzzweck
geschrieben worden. Sie enthält Methoden, die hier überhaupt nicht verwendet werden. Sie stellt
ein allgemeines Rechteck dar und kann überall eingesetzt werden, wo die Beschreibung eines
Rechtecks benötigt wird.

Um das Girokonto-Beispiel weiter auszubauen, könnten weitere Klassen geschrieben werden,


die gemeinsam die Erstellung eines komplexen Programmes zum Einsatz in einer Bank
ermöglichen:

Kunde, um mehr als den Namen eines Bankkunden zu speichern


Währung, um Konten in verschiedenen Währungen führen zu können
Sparbuch, um auch Sparbücher darstellen zu können
Verwaltung, um mehrere Konten zu speichern, neue eröffnen und auflösen zu können
viele weitere…

20.07.2023 35 von 53
KLA - Eigene Klassen programmieren

Zusammenfassung

Klassen sind die Baupläne für Objekte. Sie enthalten Attribute, Konstruktoren und Methoden.
Sie modellieren eine Sache aus der Wirklichkeit, Probleme werden meist durch die
Zusammenarbeit mehrerer Klassen gelöst.

Der Dateiname und die in der Datei definierte (öffentliche) Klasse müssen übereinstimmen.

Attribute definiert man mit:


private Datentyp attributbezeichner;
Sie legen fest, welche Einzelinformationen in den Objekten der Klasse gespeichert werden.

Innerhalb der Konstruktoren und Methoden der Klasse greift man mit
this.attributbezeichner auf die Attribute zu.

Konstruktoren heißen immer genauso wie die Klasse. Sie haben keinen Rückgabewert.

Aufgabe des Konstruktors ist es, alle Attribute des Objektes zu initialisieren.

Man kann beliebig viele Konstruktoren anbieten, die sich in ihren Parameterlisten
unterscheiden. Man spricht von Überladung.

Ist in einer Klasse kein Konstruktor implementiert, steht automatisch der implizite
Defaultkonstruktor zur Verfügung, der alle Attribute mit 0, 0.0, false bzw. null
initialisiert.

Mit final gekennzeichneten Attributen kann man nur ein einziges Mal einen Wert zuweisen,
üblicherweise im Konstruktor.

Methoden beschreiben die Operationen, die man mit einem Objekt durchführen kann. Der
Code arbeitet mit den in den Attributen gespeicherten Werten.

Spezielle Methoden sind die Getter zum Lesen eines Attributs und die Setter zum
Hineinschreiben eines neuen Wertes.

Alle Klassenmitglieder können mit den Sichtbarkeitsmodifizierern public, private und


protected gekennzeichnet werden. public bedeutet, dass das Mitglied überall im
gesamten Programm verwendet werden kann, private, dass nur innerhalb der Klasse
Zugriff besteht. Der Sichtbarkeitsmodifizierer private ist ein wichtiger Bestandteil der
Datenkapselung.

Für die Wiederverwendbarkeit einer Klasse ist die Dokumentation jedes einzelnen
Klassenmitglieds sehr wichtig.

Sie sind am Ende dieser Lerneinheit angelangt. Auf den folgenden Seiten finden Sie noch die
Übungen zur Wissensüberprüfung und die Einsendeaufgabe.

20.07.2023 36 von 53
KLA - Eigene Klassen programmieren

Wissensüberprüfung

Übung KLA-15
Multiple Choice
Attribut verwenden
Sie haben eine Klasse begonnen:
public class MeineKlasse() {
private double eigenschaft;
}

Was müssen Sie schreiben, wenn Sie in einer Methode dieser Klasse den Wert
dieses Attributs verwenden wollen?
Richtig Falsch Auswertung
this.eigenschaft

this

double eigenschaft

eigenschaft

MeineKlasse.eigenschaft

Übung KLA-16
Multiple Choice Konstruktor vs. Instanzmethode
Was unterscheidet die Definition eines Konstruktors von der Definition einer
Instanzmethode?
Richtig Falsch Auswertung
Bei einem Konstruktor wird kein Rückgabedatentyp angegeben,
auch nicht void. Bei einer Instanzmethode ist die Angabe des
Ergebnistyps zwingend erforderlich - gibt es kein Ergebnis,
schreibt man void.

Konstruktoren können Parameter in den runden Klammern


haben, Instanzmethoden nicht.

Konstruktoren werden mit dem Schlüsselwort static


gekennzeichnet, Instanzmethoden nicht.

Ein Konstruktor heißt immer genauso wie die Klasse selbst, eine
Instanzmethode kann (und sollte) einen anderen Namen tragen.

20.07.2023 37 von 53
KLA - Eigene Klassen programmieren

Übung KLA-17
Multiple Choice
Instanzmethoden
Welche Aussagen über Instanzmethoden sind korrekt?
Richtig Falsch Auswertung
Instanzmethoden arbeiten mit den Attributen des aktuellen
Objekts this, sie nehmen Änderungen daran vor und/oder
berechnen daraus Ergebnisse.

Instanzmethoden arbeiten mit den Attributen aller Objekte


gleichzeitig. Änderungen der Attribute sind in allen Objekten
sichtbar.

Instanzmethoden werden so geschrieben:


public rueckgabetyp methodenname(datentyp parameter)

Instanzmethoden werden mit dem Schlüsselwort static


gekennzeichnet.

Instanzmethoden werden so geschrieben:public


methodenname(datentyp parameter)

In Instanzmethoden darf man this benutzen.

Übung KLA-18
Multiple Choice get-Methode
Sie haben eine Klasse begonnen:
public class MeineKlasse() {
private double eigenschaft;
}

Wie sollte die get-Methode für das Attribut aussehen?


Richtig Falsch Auswertung
public double geteigenschaft() {
return eigenschaft;
}

public void getEigenschaft( double eigenschaft) {


return eigenschaft;
}

public int getEigenschaft() {


return eigenschaft;
}

public double getEigenschaft() {


return eigenschaft;
}

20.07.2023 38 von 53
KLA - Eigene Klassen programmieren

Einsendeaufgaben

KLA-E1
Einsendeaufgabe
Mathematischer Bruch
Schreiben Sie eine Klasse namens Bruch, die einen mathematischen Bruch darstellt:
1. Jeder Bruch besteht aus einem ganzzahligen Zähler und einem ganzzahligen
Nenner. Geben Sie der Klasse also zwei Attribute.
2. Die Klasse soll einen Konstruktor mit zwei Parametern haben, dem Zähler und
dem Nenner.
3. Die Klasse soll zusätzlich einen Konstruktor haben mit nur einem Parameter für
den Zähler. Das Nenner-Attribut wird vom Konstruktor auf 1 gesetzt. Rufen Sie
den Konstruktor aus Punkt 2 auf.
4. Geben Sie der Klasse folgende Methoden:
get-Methode für Zähler und Nenner
public Bruch multiplizieren(Bruch b)
rechnet this * b aus. Brüche werden multipliziert, indem man jeweils die
beiden Zähler und die beiden Nenner miteinander multipliziert und einen
neuen Bruch daraus erzeugt.
public double ausrechnen()
rechnet den Bruch in eine Kommazahl um. (Denken Sie an die Besonderheit
des Divisionsoperators: er teilt ganzzahlig, wenn er zwischen ganzzahligen
Werten steht.)
public String toString()
liefert eine String-Darstellung des Bruches, z. B. „1/2“.
5. Schreiben Sie ein Hauptprogramm:
Die Nutzenden sollen Zähler und Nenner zweier Brüche (insgesamt also 4
Zahlen) eingeben. (Tipp: statische Methoden der Klasse EinAusgabe
nutzen!)
Erzeugen Sie zwei Objekte vom Typ Bruch und speichern Sie sie in zwei
Variablen.
Rufen Sie die Methode multiplizieren auf und speichern Sie das Ergebnis
in einer weiteren Variablen.
Geben Sie die eingegebenen Brüche zusammen mit dem Ergebnis der
Multiplikation aus.
Vorgabe:
Dreieck.java (4 KB)
EinAusgabe.java (7 KB)
Abgabe
An die Mentoren der Hochschule, an der Sie eingeschrieben sind, senden Sie bitte
folgenden Dateien:
die Quelldateien Bruch.java, BruchMain.java, EinAusgabe.java
die übersetzten Dateien Bruch.class, BruchMain.class,
EinAusgabe.class
als .zip-Datei mit dem Namen IhrName_LEKLA-E1.zip.
Weitere Informationen, insbesondere den Abgabetermin, entnehmen Sie den
Ankündigungen im Lernraumsystem.
Bearbeitungszeit: 45 Minuten

20.07.2023 39 von 53
KLA - Eigene Klassen programmieren

KLA-E2
Einsendeaufgabe Kunde einer Bank
Schreiben Sie eine Klasse namens Kunde. Sie soll den Kunden einer Bank darstellen,
der Konten besitzen kann.
1. Die Klasse soll Attribute für
den Vornamen (String)
den Nachnamen (String)
die Adresse (String)
das Geburtsdatum (java.time.LocalDate)
haben.
2. Schreiben Sie einen Konstruktor, der für alle Attribute Parameter hat. Die Adresse
sollte keine leere Zeichenkette ("") und nicht null sein. Schreiben Sie ggf.
„unbekannt“ in das Attribut. Das Geburtsdatum soll nicht null sein, schreiben Sie
ggf. den Rückgabewert der statischen Methode LocalDate.now() in das
Attribut.
3. Geben Sie der Klasse get-Methoden für Adress- und Geburtstagsattribut.
4. Geben Sie der Klasse eine set-Methode für die Adresse. Die Adresse sollte keine
leere Zeichenkette ("") und auch nicht null sein.
5. Schreiben Sie folgende Methoden:
public String getVollstaendigerName()
sie liefert Vor- und Nachnamen zusammengesetzt zurück.
public int getAlter()
Sie liefert zurück, wie alt der Kunde ist.(siehe unten)
public String toString()
gibt eine String-Darstellung der Kundendaten zurück (Tipp: statische Methode
datumFormatiert in EinAusgabe)
public Girokonto kontoErstellen()
Sie erzeugt ein neues Girokonto für diesen Kunden, d. h. der vollständige
Name von this wird als Kontoinhaber eingetragen.
6. Schreiben Sie ein Hauptprogramm:
Die Nutzenden sollen ihren Namen, ihre Adresse und ihr Geburtsdatum
eingeben. (Tipp: statische Methoden der Klasse EinAusgabe nutzen!)
Geben Sie alle gespeicherten Daten des Kunden und sein Alter aus.
Erzeugen Sie ein neues Konto für den Kunden und geben Sie alle Daten des
neu erzeugten Girokontos in der Eingabeaufforderung (Terminal) aus.
Um das Alter zu bestimmen, helfen folgende Methoden und Klassen:
In der Klasse java.time.LocalDate gibt es die statische Methode
public static LocalDate now()
Sie liefert das heutige Datum zurück, damit Sie es in einer Variablen speichern
können.
Die Klasse java.time.Period stellt eine Zeitdauer, also z. B. den Abstand
zwischen dem Geburtstag und dem heutigen Tag, dar und hat folgende praktische
Methoden:
public static Period between(LocalDate start, LocalDate ende)
Sie berechnet den Abstand zwischen den beiden Datumsangaben start und
ende und gibt ihn als Period-Objekt zurück.
public int getYears()
gibt zurück, aus wie vielen vollen Jahren die Zeitdauer this besteht.
Vorgabe:
EinAusgabe.java (7 KB)

20.07.2023 40 von 53
KLA - Eigene Klassen programmieren

Dreieck.java (4 KB)
Girokonto.java (6 KB)
Abgabe
An die Mentoren der Hochschule, an der Sie eingeschrieben sind, senden Sie bitte
folgenden Dateien:
die Quelldateien Kunde.java, KundeTest.java
die übersetzten Dateien Kunde.class, KundeTest.class
als .zip-Datei mit dem Namen IhrName_LEKLA-E2.zip.
Weitere Informationen, insbesondere den Abgabetermin, entnehmen Sie den
Ankündigungen im Lernraumsystem.
Bearbeitungszeit: 60 Minuten

20.07.2023 41 von 53
KLA - Eigene Klassen programmieren

Appendix

Lösung Übung KLA-02

Wenn kontostand public ist, lässt sich der Code problemlos kompilieren und ausführen. Ebenso
ohne Sichtbarkeitsmodifizierer, weil die beiden Klassen Girokonto und PublicZugriff im
gleichen Paket liegen. Wird kontostand als private deklariert, reagiert der Compiler mit
dieser Fehlermeldung:

PublicZugriff.java:16: error kontostand has private access in Girokonto


meins.kontostand = 1000000000;
^
PublicZugriff.java:18: error kontostand has private access in Girokonto
jemandAnders.kontostand = -123456789;
^
2 errors

20.07.2023 42 von 53
KLA - Eigene Klassen programmieren

Lösung Übung KLA-03

zu 1.
In Abschnitt 2.1 steht die Lösung für diese Aufgabe: Der implizite Defaultkonstruktor initialisiert
alle Attribute automatisch mit 0, 0.0, false bzw. null. Entsprechend hat Hans also 0.00 € auf
seinem Konto und die Kontonummer 0.

zu 2.
Zurzeit sind die Inhaber beider Girokonto-Objekte null, da es sich bei String auch um eine
Klasse handelt. Dieser Fehlerwert zeigt an, dass in diesem Attribut noch kein Objekt gespeichert
wurde.
Girokonto.java
001 /**
002 * Die Objekte dieser Klasse stellen Girokonten bei einer Bank dar. Modelliert
003 * werden der Inhaber, die Kontonummer und der Kontostand des Girokontos. Der
004 * Kontostand ist dabei nie negativ.
005 *
006 * @author Dorothea Hubrich
007 *
008 */
009 public class Girokonto {
010 /**
011 * die Kontonummer
012 */
013 private long kontonummer;
014 /**
015 * der Kontostand, immer positiv
016 */
017 private double kontostand;
018 /**
019 * Der Name des Inhabers
020 */
021 private String inhaber;
022
023 /**
024 * @return die Kontonummer
025 */
026 public long getKontonummer() {
027 return this.kontonummer;
028 }
029
030 /**
031 * @return aktueller Kontostand
032 */
033 public double getKontostand() {
034 return this.kontostand;
035 }
036
037 /**
038 * @return Name des Inhabers
039 */
040 public String getInhaber() {
041 return this.inhaber;
042 }
043
044 }
Girokonto.java (1 KB)

20.07.2023 43 von 53
KLA - Eigene Klassen programmieren

KleineBank.java
001 /**
002 * ein kleines Bank-Programm
003 *
004 * @author Dorothea Hubrich
005 *
006 */
007 public class KleineBank {
008
009 /**
010 * erstellt zwei Girokonten und transferiert Geld von einem zum anderen
011 *
012 * @param args
013 */
014 public static void main(String[] args) {
015 Girokonto hansKonto;
016 Girokonto ottosKonto;
017 hansKonto = new Girokonto();
018 ottosKonto = new Girokonto();
019
020 /*
021 * Das Ziel-Programm steht hier nur als Kommentar, damit Sie wissen, wo
022 * es hingehen soll. Nach und nach wird der Kommentar kleiner werden.
023
024 hansKonto = new Girokonto("Hans");
025 ottosKonto = new Girokonto("Otto", 1000);
026 */
027
028 double hansStand;
029 hansStand = hansKonto.getKontostand();
030 long hansNr;
031 hansNr = hansKonto.getKontonummer();
032 String hansInhaber;
033 hansInhaber = hansKonto.getInhaber();
034 System.out.println("Hans hat im Moment " + hansStand
035 + " EUR auf dem Konto " + " mit der Nummer " + hansNr);
036 System.out.println("Als Inhaber dieses Kontos ist " + hansInhaber
037 + " eingetragen.");
038 double ottosStand;
039 ottosStand = ottosKonto.getKontostand();
040 long ottosNr;
041 ottosNr = ottosKonto.getKontonummer();
042 String ottosInhaber;
043 ottosInhaber = ottosKonto.getInhaber();
044 System.out.println("Otto hat im Moment " + ottosStand
045 + " EUR auf dem Konto " + " mit der Nummer " + ottosNr);
046 System.out.println("Als Inhaber dieses Kontos ist " + ottosInhaber
047 + " eingetragen.");
048 /*
049 boolean hatGeklappt;
050 hatGeklappt = ottosKonto.abheben(200);
051 if (hatGeklappt == true) {
052 System.out.println("Die Abhebung war erfolgreich!");
053 double ottosStand;
054 ottosStand = ottosKonto.getKontostand();
055 System.out.println("Neuer Kontostand bei Otto: " + ottosStand);
056 hansKonto.einzahlen(200);
057 }
058 System.out.println("Alle Daten von Hans: " + hansKonto);
059 */
060 }
061
062 }
KleineBank.java (2 KB)

20.07.2023 44 von 53
KLA - Eigene Klassen programmieren

Lösung Übung KLA-04

Antwort:
Lieber nicht. Man schreibt Klassen nicht nur für ein einziges Programm, sondern damit sie später
in anderen Zusammenhängen wiederverwendet werden können. Vielleicht möchten andere
Entwickelnde in einem anderen Programm den Kontostand wirklich als Zahl wissen, um z. B. die
Kontostände mehrerer Konten zusammenaddieren zu können. Lassen Sie also eine Methode,
die mit großer Wahrscheinlichkeit nützlich sein könnte, stehen.

GiroKonto.java
001 import java.text.NumberFormat;
002
003 /**
004 * Die Objekte dieser Klasse stellen Girokonten bei einer Bank dar. Modelliert
005 * werden der Inhaber, die Kontonummer und der Kontostand des Girokontos. Der
006 * Kontostand ist dabei nie negativ.
007 *
008 * @author Dorothea Hubrich
009 *
010 */
011 public class Girokonto {
012 /**
013 * die Kontonummer
014 */
015 private long kontonummer;
016 /**
017 * der Kontostand, immer positiv
018 */
019 private double kontostand;
020 /**
021 * Der Name des Inhabers
022 */
023 private String inhaber;
024
025 /**
026 * @return die Kontonummer
027 */
028 public long getKontonummer() {
029 return this.kontonummer;
030 }
031
032 /**
033 * @return aktueller Kontostand
034 */
035 public double getKontostand() {
036 return this.kontostand;
037 }
038
039 /**
040 * liefert den Kontostand als String fuer die Ausgabe formatiert
041 *
042 * @return Kontostand mit 2 Nachkommastellen und Euro-Zeichen
043 */
044 public String getStandFormatiert() {
045 NumberFormat nf = NumberFormat.getCurrencyInstance();
046 String ausgabetext = nf.format(this.kontostand);
047 return ausgabetext;
048 }
049
050 /**
051 * @return Name des Inhabers
052 */
053 public String getInhaber() {
054 return this.inhaber;
055 }
056
057 }
Girokonto.java (1 KB)

20.07.2023 45 von 53
KLA - Eigene Klassen programmieren

KleineBank.java
001 /**
002 * ein kleines Bank-Programm
003 *
004 * @author Dorothea Hubrich
005 *
006 */
007 public class KleineBank {
008
009 /**
010 * erstellt zwei Girokonten und transferiert Geld von einem zum anderen
011 *
012 * @param args
013 */
014 public static void main(String[] args) {
015 Girokonto hansKonto;
016 Girokonto ottosKonto;
017 hansKonto = new Girokonto();
018 ottosKonto = new Girokonto();
019
020 /*
021 * Das Ziel-Programm steht hier nur als Kommentar, damit Sie wissen, wo
022 * es hingehen soll. Nach und nach wird der Kommentar kleiner werden.
023
024 hansKonto = new Girokonto("Hans");
025 ottosKonto = new Girokonto("Otto", 1000);
026 */
027 String hansStand;
028 hansStand = hansKonto.getStandFormatiert();
029 long hansNr;
030 hansNr = hansKonto.getKontonummer();
031 String hansInhaber;
032 hansInhaber = hansKonto.getInhaber();
033 System.out.println("Hans hat im Moment " + hansStand
034 + " auf dem Konto mit der Nummer " + hansNr);
035 System.out.println("Als Inhaber dieses Kontos ist " + hansInhaber
036 + " eingetragen.");
037 String ottosStand;
038 ottosStand = ottosKonto.getStandFormatiert();
039 long ottosNr;
040 ottosNr = ottosKonto.getKontonummer();
041 String ottosInhaber;
042 ottosInhaber = ottosKonto.getInhaber();
043 System.out.println("Otto hat im Moment " + ottosStand
044 + " auf dem Konto mit der Nummer " + ottosNr);
045 System.out.println("Als Inhaber dieses Kontos ist " + ottosInhaber
046 + " eingetragen.");
047 /*
048 boolean hatGeklappt;
049 hatGeklappt = ottosKonto.abheben(200);
050 if (hatGeklappt == true) {
051 System.out.println("Die Abhebung war erfolgreich!");
052 double ottosStand;
053 ottosStand = ottosKonto.getKontostand();
054 System.out.println("Neuer Kontostand bei Otto: " + ottosStand);
055 hansKonto.einzahlen(200);
056 }
057 System.out.println("Alle Daten von Hans: " + hansKonto);
058 */
059 }
060
061 }
KleineBank.java (2 KB)

20.07.2023 46 von 53
KLA - Eigene Klassen programmieren

Lösung Übung KLA-05

Girokonto.java
001 import java.text.NumberFormat;
002
003 /**
004 * Die Objekte dieser Klasse stellen Girokonten bei einer Bank dar. Modelliert
005 * werden der Inhaber, die Kontonummer und der Kontostand des Girokontos. Der
006 * Kontostand ist dabei nie negativ.
007 *
008 * @author Dorothea Hubrich
009 *
010 */
011 public class Girokonto {
012 /**
013 * die Kontonummer
014 */
015 private long kontonummer;
016 /**
017 * der Kontostand, immer positiv
018 */
019 private double kontostand;
020 /**
021 * Der Name des Inhabers
022 */
023 private String inhaber;
024
025 /**
026 * @return die Kontonummer
027 */
028 public long getKontonummer() {
029 return this.kontonummer;
030 }
031
032 /**
033 * @return aktueller Kontostand
034 */
035 public double getKontostand() {
036 return this.kontostand;
037 }
038
039 /**
040 * liefert den Kontostand als String fuer die Ausgabe formatiert
041 *
042 * @return Kontostand mit 2 Nachkommastellen und Euro-Zeichen
043 */
044 public String getStandFormatiert() {
045 NumberFormat nf = NumberFormat.getCurrencyInstance();
046 String ausgabetext = nf.format(this.kontostand);
047 return ausgabetext;
048 }
049
050 /**
051 * @param der Name des neuen Inhabers
052 */
053 public void setInhaber(String inhaber) {
054 boolean inOrdnung = inhaber != null && !inhaber.equals("");
055 if (inOrdnung == true)
056
057 {
058 this.inhaber = inhaber;
059 }
060 }
061
062 /**
063 * @return Name des Inhabers
064 */
065 public String getInhaber() {
066 return this.inhaber;
067 }
068
069 }
070
Girokonto.java (1 KB)

KleineBank.java
20.07.2023 47 von 53
KLA - Eigene Klassen programmieren

001 /**
002 * ein kleines Bank-Programm
003 *
004 * @author Dorothea Hubrich
005 *
006 */
007 public class KleineBank {
008
009 /**
010 * erstellt zwei Girokonten und transferiert Geld von einem zum anderen
011 *
012 * @param args
013 */
014 public static void main(String[] args) {
015 Girokonto hansKonto;
016 Girokonto ottosKonto;
017 hansKonto = new Girokonto();
018 hansKonto.setInhaber("Hans");
019 ottosKonto = new Girokonto();
020 ottosKonto.setInhaber("Otto");
021
022 /*
023 * Das Ziel-Programm steht hier nur als Kommentar, damit Sie wissen, wo
024 * es hingehen soll. Nach und nach wird der Kommentar kleiner werden.
025
026 hansKonto = new Girokonto("Hans");
027 ottosKonto = new Girokonto("Otto", 1000);
028 */
029 String hansStand;
030 hansStand = hansKonto.getStandFormatiert();
031 long hansNr;
032 hansNr = hansKonto.getKontonummer();
033 String hansInhaber;
034 hansInhaber = hansKonto.getInhaber();
035 System.out.println("Hans hat im Moment " + hansStand + " auf dem Konto "
036 + " mit der Nummer " + hansNr);
037 System.out.println("Als Inhaber dieses Kontos ist " + hansInhaber
038 + " eingetragen.");
039 String ottosStandForm;
040 ottosStandForm = ottosKonto.getStandFormatiert();
041 long ottosNr;
042 ottosNr = ottosKonto.getKontonummer();
043 String ottosInhaber;
044 ottosInhaber = ottosKonto.getInhaber();
045 System.out.println("Otto hat im Moment " + ottosStandForm
046 + " auf dem Konto mit der Nummer " + ottosNr);
047 System.out.println("Als Inhaber dieses Kontos ist " + ottosInhaber
048 + " eingetragen.");
049
050 // Inhaberwechsel:
051 hansKonto.setInhaber("Eva");
052 System.out.println(
053 "Jetzt gehoert Hans' Konto: " + hansKonto.getInhaber());
054 System.out.println("Lieber wieder rueckgaengig machen...");
055 hansKonto.setInhaber("Hans");
056 System.out.println(
057 "Jetzt gehoert Hans' Konto: " + hansKonto.getInhaber());
058 // Das sollte keine Aenderung bewirken:
059 hansKonto.setInhaber("");
060 System.out.println(
061 "Jetzt gehoert Hans' Konto: " + hansKonto.getInhaber());
062
063 /*
064 boolean hatGeklappt;
065 hatGeklappt = ottosKonto.abheben(200);
066 if (hatGeklappt == true) {
067 System.out.println("Die Abhebung war erfolgreich!");
068 double ottosStand;
069 ottosStand = ottosKonto.getKontostand();
070 System.out.println("Neuer Kontostand bei Otto: " + ottosStand);
071 hansKonto.einzahlen(200);
072 }
073 System.out.println("Alle Daten von Hans: " + hansKonto);
074 */
075 }
076
077 }
KleineBank.java (2 KB)

20.07.2023 48 von 53
KLA - Eigene Klassen programmieren

Lösung Übung KLA-06

zu 1.

Die Abhebung wird im Moment nicht ausgeführt, da der implizite Defaultkonstruktor den
Kontostand von Otto erst einmal auf 0 gesetzt hat.

zu 2.

Dreieck.java (4 KB)

EinAusgabe.java (6 KB)

Ausschnitt aus Girokonto.java


import java.text.NumberFormat;

/**
* Die Objekte dieser Klasse stellen Girokonten bei einer Bank dar. Modelliert
* werden der Inhaber, die Kontonummer und der Kontostand des Girokontos. Der
* Kontostand ist dabei nie negativ.
*
* @author Dorothea Hubrich
*
*/
public class Girokonto {
...

/**
* berechnet die Zinsen gemaess dem uebergebenen Zinssatz und addiert sie
* zum aktuellen Kontostand
*
* @param zinssatzInProzent ein Wert zwischen 0 und 100
* @return die berechneten Zinsen oder 0, wenn der zinssatzInProzent nicht
* zwischen 0 und 100 liegt.
*/
public double zinsenDazu(double zinssatzInProzent) {
if (zinssatzInProzent < 0 || zinssatzInProzent > 100) {
return 0;
}
double zinsen;
zinsen = this.kontostand * zinssatzInProzent / 100.0;
this.kontostand = this.kontostand + zinsen;
return zinsen;
}

...
}
Girokonto.java (3 KB)

20.07.2023 49 von 53
KLA - Eigene Klassen programmieren

Ausschnitt aus KleineBank.java


/**
* ein kleines Bank-Programm
*
* @author Dorothea Hubrich
*
*/
public class KleineBank {
/**
* erstellt zwei Girokonten und transferiert Geld von einem zum anderen
*
* @param args
*/
public static void main(String[] args) {
...

// Zinsberechnung:
double zinssatz;
zinssatz = EinAusgabe
.eingabeKommazahl("Wie hoch ist zur Zeit der Zinssatz? ");
double berechneteZinsen;
berechneteZinsen = hansKonto.zinsenDazu(zinssatz);
System.out.println(
"Hans hat " + berechneteZinsen + " EUR an Zinsen erhalten.");
hansStand = hansKonto.getStandFormatiert();
System.out.println("Sein Kontostand betraegt jetzt: " + hansStand);

...
}
}
KleineBank.java (3 KB)

Hinweis: Damit die Datei EinAusgabe.java kompiliert, ist die Datei Dreieck.java nötig!

zu 3.

Dreieck.java (4 KB)

EinAusgabe.java (6 KB)

Ausschnitt aus Girokonto.java


import java.text.NumberFormat;

/**
* Die Objekte dieser Klasse stellen Girokonten bei einer Bank dar. Modelliert
* werden der Inhaber, die Kontonummer und der Kontostand des Girokontos. Der
* Kontostand ist dabei nie negativ.
*
* @author Dorothea Hubrich
*
*/
public class Girokonto {
...

/**
* Ueberweist den angegebenen Betrag von this auf das Empfaenger-Konto
*
* @param betrag Ueberweisungsbetrag
* @param empfaenger Konto des Empfaengers
* @return true, wenn die Ueberweisung ausgefuehrt werden konnte;
* false, wenn nicht.
*/
public boolean ueberweisen(double betrag, Girokonto empfaenger) {
boolean geklappt;
geklappt = this.abheben(betrag);
if (geklappt == true) {
empfaenger.einzahlen(betrag);
return true;
}
return false;
}

...
}
Girokonto.java (4 KB)

20.07.2023 50 von 53
KLA - Eigene Klassen programmieren

Ausschnitt aus KleineBank.java


/**
* ein kleines Bank-Programm
*
* @author Dorothea Hubrich
*
*/
public class KleineBank {
/**
* erstellt zwei Girokonten und transferiert Geld von einem zum anderen
*
* @param args
*/
public static void main(String[] args) {
...

hatGeklappt = hansKonto.ueberweisen(100, ottosKonto);


if (hatGeklappt == true) {
System.out.println("Die Ueberweisung war erfolgreich!");
}

...
}
}
KleineBank.java (4 KB)

Hinweis: Damit die Datei EinAusgabe.java kompiliert, ist die Datei Dreieck.java nötig!

Lösungshinweis: Übung KLA-07

Zum einen sollten Sie feststellen, dass der Compiler die Methode toString als zum Girokonto-
Objekt gehörig erkennt, obwohl Sie diese bisher nicht selbst geschrieben haben. Zum anderen
sollten beide Anweisungen eine identische Ausgabe erzeugen. Ob Sie also toString selbst
aufrufen oder das dem System.out.println überlassen, spielt keine Rolle. Selbstverständlich
gilt das für alle Objekte egal welcher Klasse, nicht nur für hansKonto.

Lösung Übung KLA-08

zu 1.

Ausgabe in der Eingabeaufforderung (Terminal):

Auf dem Girokonto 0 von Hans sind 210,00 €.

zu 2.

Ausgabe in der Eingabeaufforderung (Terminal):

.\Girokonto.java:112: error: method does not override or implement a method from a


supertype
@Override
^
1 error

20.07.2023 51 von 53
KLA - Eigene Klassen programmieren

Lösung: Übung KLA-10

Ausgabe in der Eingabeaufforderung (Terminal):

.\Girokonto.java:25: error: non-static variable this cannot be referenced from a static


context
this.kontonummer = groessteNummer;
^
1 error

Lösung Übung KLA-12

Ausschnitt aus Girokonto.java


/**
* Die Objekte dieser Klasse stellen Girokonten bei einer Bank dar. Modelliert
* werden der Inhaber, die Kontonummer und der Kontostand des Girokontos. Der
* Kontostand ist dabei nie negativ.
*
* @author Dorothea Hubrich
*
*/
public class Girokonto {
...

/**
* Dieser Konstruktor erstellt ein Konto fuer den angegebenen Inhaber mit
* dem angegebenen Kontostand
*
* @param inhaber der neue Kontoinhaber
* @param anfangsstand der anfaengliche Kontostand; darf nicht negativ sein
*/
public Girokonto(String inhaber, double anfangsstand) {
this.inhaber = "unbekannt";
boolean inOrdnung = inhaber != null && !inhaber.equals("");
if (inOrdnung == true) {
this.inhaber = inhaber;
}
this.kontostand = 0.0;
if (anfangsstand >= 0) {
this.kontostand = anfangsstand;
}
this.kontonummer = Girokonto.holeNeueNummer();
}

...
}
Girokonto.java (6 KB)

Ausschnitt aus KleineBank.java


/**
* ein kleines Bank-Programm
*
* @author Dorothea Hubrich
*
*/
public class KleineBank {
/**
* erstellt zwei Girokonten und transferiert Geld von einem zum anderen
*
* @param args
*/
public static void main(String[] args) {
Girokonto hansKonto;
Girokonto ottosKonto;
hansKonto = new Girokonto("Hans");
ottosKonto = new Girokonto("Otto", 1000);

...
}
}
KleineBank.java (3 KB)

20.07.2023 52 von 53
KLA - Eigene Klassen programmieren

Lösung Übung KLA-13

Ausgabe in der Eingabeaufforderung (Terminal) bei Verstoß gegen die Syntax-Regel:

.\Girokonto.java:59: error: call to this must be first statement in constructor


this(inhaber, 0.0);
^
1 error

Ausschnitt aus Girokonto.java


/**
* Die Objekte dieser Klasse stellen Girokonten bei einer Bank dar. Modelliert
* werden der Inhaber, die Kontonummer und der Kontostand des Girokontos. Der
* Kontostand ist dabei nie negativ.
*
* @author Dorothea Hubrich
*
*/
public class Girokonto {
...

/**
* Dieser Konstruktor erstellt ein leeres Konto fuer den angegebenen Inhaber
*
* @param inhaber der neue Kontoinhaber
*/
public Girokonto(String inhaber) {
this(inhaber, 0.0);
}

/**
* Dieser Konstruktor erstellt ein Konto fuer den angegebenen Inhaber mit
* dem angegebenen Kontostand
*
* @param inhaber der neue Kontoinhaber
* @param anfangsstand der anfaengliche Kontostand; darf nicht negativ sein
*/
public Girokonto(String inhaber, double anfangsstand) {
this.inhaber = "unbekannt";
boolean inOrdnung = inhaber != null && !inhaber.equals("");
if (inOrdnung == true) {
this.inhaber = inhaber;
}
this.kontostand = 0.0;
if (anfangsstand >= 0) {
this.kontostand = anfangsstand;
}
this.kontonummer = Girokonto.holeNeueNummer();
}
...
}
Girokonto.java (4,7 KB)

KleineBank.java (1,9 KB)

Lösung Übung KLA-14

Reaktion des Compilers:

.\Girokonto.java:49: error: variable kontonummer might already have been assigned


this.kontonummer = 99999;
^
1 error

20.07.2023 53 von 53

Das könnte Ihnen auch gefallen