JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung

 
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
Einführung in die
Programmiersprache
        JAVA

 unter Verwendung der Entwicklungsumgebung
                    BlueJ

              Text von K.Spier (2004),
        überarbeitet von B.Spier (2009-2014)
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
JAVA-Einführung, Seite 2

Inhaltsverzeichnis

Kapitel 1: Vorstellung der Entwicklungsumgebung BlueJ und erstes Projekt ................................                                             3
Installation .....................................................................................................................................    3
Projekt Beispiel_1 (Quader) ...........................................................................................................               4
Der Editor von BlueJ für JAVA-Quelltexte ......................................................................................                       5
Kapitel 2: Zweites Projekt: Bankkonto (Bank_1) ........................................................................... 8
Erstellen einer vollständigen Übersicht zur Klasse 'Konto' (Dokumentation) ............................. 10
Kapitel 3: Drittes Projekt: Bank_2 ............................................................................................... 11
Informationen zu private und public ........................................................................................... 15
Kapitel 4: Viertes Projekt: Fahrkartenautomat ............................................................................ 16
Zahlen formatieren ..................................................................................................................... 17
Kapitel 5: Fünftes Projekt: Person (Vererbung / GregorianCalendar) ......................................... 18
Vererbung .................................................................................................................................... 21
Überschreiben von Methoden ...................................................................................................... 22
Kapitel 6: Sechstes Projekt: Wir programmieren ein Applet ........................................................ 24
Aufbau eines HTML-Quelltextes .................................................................................................. 25
Kapitel 7: Siebentes Projekt: Das Applet reagiert auf eine Maus-Aktion ..................................... 27
Kapitel 8: Achtes Projekt: Das Puzzle mit 25 Feldern .................................................................                               32
Klassenvariablen und Instanzvariablen .......................................................................................                        32
Array ............................................................................................................................................   33
For-Schleife .................................................................................................................................       34
Start und Stop .............................................................................................................................         34
While-Schleife ..............................................................................................................................        35
Kapitel 9: Was haben wir jetzt gelernt? (Wdh. und kleine Ergänzungen) .................................... 37
(Klassen, Variablen, Methoden, Konstruktoren, Fallunterscheidung, Schleifen)
Kapitel 10: Schlussbemerkung ................................................................................................... 39

Anhang .......................................................................................................................................       40
JAVA-Programm ohne Entwicklungsumgebung erstellen ............................................................                                       40
Listen, die nur Instanzen einer einzigen Klasse verwalten............................................................                                41
Formatierungen von numerischen Werten (2 Beispiele für String.format).....................................                                           42
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
JAVA-Einführung, Seite 3

Vorbemerkung
Mit JAVA wurde eine objektorientierte Programmiersprache entwickelt, die unabhängig vom
Betriebssystem des Computers ist, auf dem die Programme laufen. Es gibt viele so genannte
Entwicklungsumgebungen, um JAVA-Programme zu erstellen. Eine Entwicklungsumgebung ist
zwar nicht Voraussetzung zum Programmieren – JAVA-Programme ließen sich auch mit einem
einfachen Texteditor erstellen. Mit einem Compiler können daraus Dateien erstellt werden, die ein
JAVA-Runtime-Environment ausführen kann, solche Datei kann also ein fertiges Programm aufge-
fasst werden. Mit Hilfe einer Entwicklungsumgebung können Quelltexte sowohl erstellt als auch
kompiliert und ausgeführt werden, dadurch sind die Arbeitsschritte erheblich einfacher und
übersichtlicher. Außerdem ist der Editor dann üblicherweise mit Syntaxhervorhebung (s. S. 5)
versehen, so dass die Programmstruktur besonders gut sichtbar wird. Interessierte finden im Anhang
eine kurze Beschreibung, wie man auch ohne Entwicklungsumgebung ein JAVA-Programm
erstellen kann.
Für den Einstieg in das Programmieren mit JAVA ist BlueJ besonders gut geeignet.

1. Vorstellung der Entwicklungsumgebung BlueJ und erstes Projekt
JAVA installieren
JAVA wird durch Ausführen der Datei jdk-7u25-windows-i586.exe1 oder auf 64-Bit-Systemen
jdk-7u25-windows-x64.exe installiert. (Ein Java-Runtime-Environment jre..., das mit OpenOffice,
Geogebra oder anderen Programmen vielleicht bereits installiert ist, genügt nicht – für BlueJ wird
ein Java-Development-Kit jdk... benötigt. Für Download nach java se downloads oder jdk suchen!)
JAVA muss vor BlueJ installiert werden.
BlueJ installieren
BlueJ darf für Bildungszwecke verwendet werden ohne dass Lizenzgebühren zu zahlen sind. (Siehe
Homepage von BlueJ, http://www.bluej.org, Download der Version 3.1.02 von dort.)
Zur Installation wird die Datei bluejsetup-308.msi2 ausgeführt. Beim ersten Programmstart sucht
BlueJ die zu verwendende JAVA-Version und zeigt eventuell ein Auswahlfenster, wenn die
Zuordnung nicht automatisch erfolgen kann.
Spracheinstellung: Deutsch
Wenn die Entwicklungsumgebung in deutscher Sprache erscheinen soll, muss die Datei BlueJ.defs
mit einem Text-Editor bearbeitet werden, geeignet ist z.B. WordPad (Startmenü/Zubehör). Dieser
Editor muss bei aktuellen Windows-Versionen als Administrator ausgeführt werden, damit im
Installationsordner (vermutlich: C:\Programme(x86)\BlueJ\) Schreibberechtigung erreicht wird.
BlueJ.defs liegt im Unterverzeichnis lib des Installationsordners von BlueJ. Zum Öffnen muss als
Dateityp „Alle Dokumente (*.*)“ eingestellt werden.
In dieser Datei findet man (ungefähr Zeile 31) die Festlegung der bluej.language=english
Sprache: Hier kann bluej-language=english in bluej.language=german             wird zu:
geändert werden. Danach wird die Datei gespeichert.
                                                                       bluej.language=german

1 Aktuelle Version im August 2013
2 Aktuelle Version im August 2013
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
JAVA-Einführung, Seite 4

Ein Projekt beginnen: Projekt Beispiel_1
Wir starten BlueJ und wählen den Menüpunkt
Projekt/Neues Projekt.                                Info:
Es erscheint das Dialogfenster, in dem wir angeben,   In der objektorientierten Programmierung
wo das Projekt gespeichert werden soll. Ein Projekt   arbeitet man mit Objekten. (logisch)
                                                      Objekte können Eigenschaften haben.
besteht immer aus mehreren Dateien, deshalb wird      Beispiel:
für jedes Projekt ein eigener Ordner angelegt.        Ein Quader hat die Eigenschaften Länge,
Ordner, die ein BlueJ-Projekt enthalten, werden von   Breite, Höhe. Diesen Eigenschaften können
BlueJ durch ein spezielles Symbol gekennzeichnet      verschiedene Werte zugeordnet sein. Ein
(siehe Abbildung).                                    zweiter Quader hat die gleichen Eigenschaf-
                                                      ten, aber mit anderen zugeordneten Werten.
                                                      Ein Zylinder hat dagegen andere Eigenschaf-
                                                      ten, denn er ist durch Radius und Höhe
                                                      bestimmt.
                                                      Alle Quader können wir zu einer Klasse
                                                      zusammenfassen:
                                                      Wenn wir eine Klasse 'Quader' definieren,
                                                      dann legen wir darin eine Art „Bauplan“ fest.
                                                      Alle Quader sind Objekte, die nach diesem
                                                      Bauplan konstruiert werden.
                                                      In der Definition der Klasse 'Quader' wird
                                                      außer den Eigenschaften Länge, Breite, Höhe
                                                      auch eine Methode zum Erzeugen von
                                                      Quader-Objekten festgelegt, sie wird als
                                                      Konstruktor oder Constructor bezeichnet.
                                                      Anmerkungen:
                                                      1. Die genannten Begriffe werden allgemein
                                                      bei der objektorientierten Programmierung
                                                      verwendet – unabhängig davon, ob man z.B.
                                                      mit JAVA oder mit Delphi arbeitet.
                                                      2. Gelegentlich sagt man auch, in der
Mit dem Schalter „Erzeugen“ wird der Ordner mit       Definition einer Klasse wird der Objekt-Typ
dem eingegebenen Namen angelegt und die               beschrieben, und das danach konstruierte
                                                      Objekt wird auch als Objekt-Instanz
Projektdateien werden darin gespeichert.              bezeichnet.
Die Arbeitsfläche von BlueJ enthält zunächst nur
ein Symbol für eine Readme-Datei, die für eine
Beschreibung des Projekts vorgesehen ist. Nicht
nur im Schulunterricht macht es Sinn, in einer
solchen Datei eine ganz knappe Beschreibung des
Projektes anzugeben. Die Datei wird mit einem
Doppelklick auf das Symbol geöffnet, dann
bearbeitet, gespeichert und wieder geschlossen.
Nun werden wir als erstes Beispiel eine Klasse
mit Namen 'Quader' erstellen (wie im Info-Kasten
oben rechts).
Eine Klasse im Projekt erstellen
Wir klicken auf den Schalter Neue Klasse und geben als Namen für
diese Klasse Quader ein. Daraufhin erscheint ein neues Symbol für
diese Klasse in der Projektübersicht. Wir klicken doppelt auf dieses
Symbol, um die Klasse zu bearbeiten. Zunächst sehen wir schon einige Zeilen vorgegebenen Text
im Editor für unseren Java-Quelltext, den wir nach unseren Erfordernissen anpassen werden (einige
Zeilen löschen, andere ergänzen).
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
JAVA-Einführung, Seite 5

Der Editor von BlueJ für JAVA-Quelltexte
Der Editor arbeitet mit
sogenannter        Syntax-
Hervorhebung,          d.h.
dass z.B. reservierte
Wörter oder Kom-
mentare in bestimmter
Weise farblich hervor-
gehoben werden.
Die Tatsache, dass hier
der größte Teil des
Textes in blau dar-
gestellt ist, zeigt bereits,
wie wichtig Kommen-
tare in Computerpro-
grammen sind.
Bei genauem Hinsehen
können wir sogar zwei
verschiedene Arten von
Kommentaren          unter-
scheiden:
Einfache Kommentare
werden        mit     zwei
Schrägstrichen einge-
leitet und dienen oft
dem Programmierer als
Notiz.
Die anderen, die mit
/** eingeleitet, mit *
fortgesetzt und mit */
beendet werden, dienen
zusätzlich zur Informa-
tion für andere – darauf
wird später näher einge-
gangen (Seite 10). Auf
die Begriffe public und
private wird ebenfalls
später        eingegangen
(Seite 15). Wir sehen,
dass die Klassendefi-
nition mit dem Wort
class eingeleitet wird,
gefolgt vom Namen der
Klasse.
Dann folgt eine öffnende geschweifte Klammer, die zugehörige schließende Klammer steht in der
letzten Zeile.
Der BlueJ-Editor gestaltet nicht nur den Schriftstil, er hebt auch die Struktur durch die Hinter-
grundfarbe hervor (z.B. Texte innerhalb eines {}-Klammerpaares).
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
JAVA-Einführung, Seite 6

Zum Aufbau dieses Programm-Quelltextes:
Nach dem Klassennamen werden im obigen Beispiel die Eigenschaften (hier: Variablen) für die
Instanzen festgelegt: Jede Instanz, die wir gemäß diesem „Bauplan“ erzeugen, soll je eine Variable
für Länge, Breite und Höhe besitzen. Der Variablentyp wird in JAVA immer dem Variablennamen
vorangestellt. Hier wird int als Variablentyp angegeben, d.h. die aufgeführten Variablen sind vom
Typ „integer“, sie können nur ganzzahlige Werte aufnehmen. (Wir folgen damit dem Vorschlag von
BlueJ für die Variablentypen, andere lernen wir später kennen.).
Da diese Variablen hier den Instanzen zugeordnet sind, heißen sie auch Objektfelder oder
Datenfelder oder auch Instanzvariablen.
In Java sind auch Umlaute in Variablennamen zugelassen. Umlaute werden jedoch nicht in allen
Entwicklungsumgebungen (bzw. Betriebssystemen, z.B. Linux) gleich codiert. Die BlueJ-Version 3.0.5 kann
zwar Quelltexte übersetzen, in denen Methoden- oder Klassen-Bezeichner Umlaute enthalten, jedoch führen
Methodenaufrufe dann zu Fehlern. Variablen-Bezeichner können Umlaute enthalten, ohne dass es zu
Fehlern kommt. Version 3.0.8 kann offenbar gut mit Umlauten umgehen. Die Vermeidung von Umlauten und
anderen Sonderzeichen ist dennoch zu empfehlen.
Es folgt die Festlegung des Standard-Konstruktors. Der Name des Konstruktors stimmt in JAVA
immer mit dem Namen der Klasse überein. Dieser Konstruktor ist hier sehr einfach aufgebaut: Er
legt nur Werte für die Variablen eines Quaders fest, der mit ihm erzeugt wird. Alle Quader-
Instanzen, die mit diesem Konstruktor erzeugt werden, haben die gleichen Werte für die Höhe, die
Länge und die Breite. Für die Zuweisung von Werten an eine Variable wird in JAVA ein einfaches
Gleichheitszeichen verwendet (wie in BASIC, C++, aber anders als in PASCAL u. DELPHI). Auch
für den Konstruktor werden Anfang und Ende durch öffnende bzw. schließende geschweifte
Klammer gekennzeichnet. Beachten Sie die übersichtlichen Positionen aller {}-Klammerpaare!
Das Beispiel zeigt außerdem, dass eine Klasse mehrere Konstruktoren besitzen kann: Ein zweiter
Konstruktor dient dazu, Quader zu konstruieren, bei denen mit Aufruf des Konstruktors Werte für
die Länge, die Breite und die Höhe erfragt und übernommen werden.
Zum Schluss zeigt das Beispiel, dass die Klasse außer Konstruktoren auch noch andere Methoden
besitzen kann, hier zur Berechnung des Volumens. Diese Methode berechnet aus Länge, Breite und
Höhe der Quader-Instanz ihr Volumen. Durch die Angabe von return wird festgelegt, welcher Wert
bei Aufruf dieser Methode zurückgegeben wird. Bei allen Methoden, die einen Wert zurückgeben,
muss vor dem Namen der Methode – ähnlich wie bei Variablen – der Typ des Rückgabewertes
angegeben werden, hier also int für integer (ganzzahlig).
Wenn wir die Klasse 'Quader' so wie oben beschrieben festgelegt haben, lassen wir diesen Text
übersetzen (auch als compilieren bezeichnet, Schalter links oben, Shortcut Strg-k). Dabei wird
dieser Text in einen vom Computer interpretierbaren Code übersetzt. Beim Compilieren zeigen sich
(nicht nur bei Anfängern) oft kleine Fehler, die eine Übersetzung verhindern, z.B. eine fehlende
Klammer, ein fehlendes Semikolon oder ähnliches.
 Tipp 1:
 Da zu jeder öffnenden geschweiften Klammer eine schließende gehört, ist es vernünftig, nach der
 öffnenden auch gleich die schließende (in der nächsten Zeile) zu tippen. Den weiteren Text kann man
 dann dazwischen einfügen.
 Tipp 2:
 Einrückungen wie im Beispiel sind für die Interpretation des Quelltextes zwar nicht erforderlich, sie werden
 aber für die Übersichtlichkeit (auch von Profis) vorgenommen. Da die Programme mit zunehmendem
 Lernfortschritt komplizierter werden, sollte man sich diesen Stil von Anfang an zu Eigen machen.
 Beobachten Sie, wie BlueJ nach der öffnenden Klammer automatisch einrückt und die schließende
 Klammer an die passenden Position setzt! (Editor-Menü Bearbeiten, Befehl Auto-Layout, Shortcut Strg-
 Umschalt-I!) Die Einrückposition für Kommentare erreicht man am einfachsten mit der TAB-Taste.

Nach dem Kompilieren der Klasse 'Quader' werden wir mit Hilfe von BlueJ Instanzen zu dieser
Klasse erzeugen und untersuchen.
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
JAVA-Einführung, Seite 7

Instanzen der Klasse Quader erzeugen
Wenn die Klasse 'Quader' erfolgreich com-
piliert wurde, ist das Symbol für diese
Klasse nicht mehr schraffiert. Um nun eine
Instanz von dieser Klasse zu erzeugen,
klicken wir mit der rechten Maustaste auf
das Klassensymbol. Aus dem sich öffnen-
den Kontextmenü wählen wir zunächst new
Quader() aus. Der (Standard-) Konstruktor
wird ausgeführt, nachdem wir einen Namen
für die Instanz festgelegt haben. Auf dem
Hauptfenster erscheint unten ein Symbol
für das soeben erzeugte Objekt. Wir können
den Vorgang wiederholen und somit wei-
tere Instanzen derselben Klasse erzeugen.
Wählen wir das nächste Mal
aus dem Kontextmenü new
Quader(la,br,ho) aus, so werden
wir zum Ausführen des
zweiten Konstruktors nach
den Werten für die Parameter
la, br und ho gefragt: Im
oberen       Abschnitt      des
Dialogfensters wird der Kom-
mentar angezeigt, der im
Quelltext dem Konstruktor
vorangestellt worden war.
Klicken wir nun mit der rech-
ten Maustaste auf ein rotes
Objektsymbol, so können wir
u.a. aus dem Kontextmenü
auswählen, ob wir das Objekt löschen oder
untersuchen (inspizieren) wollen. Das Inspi-
zieren zeigt uns, welche Werte die Variablen
laenge, breite und hoehe besitzen. Außerdem
können wir über das Kontextmenü die Methode zur Volumenberechnung aufrufen. (Dort gezeigte
geerbte Methoden interessieren an dieser Stelle nicht.)
Fragen und Aufgaben zum Text
 1. Braucht man BlueJ, um Programme in JAVA zu schreiben?
 2. Der Begriff Objekt wird manchmal sowohl für Klasse als auch für Instanz verwendet. Erläutern
    Sie diese Begriffe an dem hier vorgestellten und an einem anderen selbst gewählten Beispiel.
 3. Muss eine Klasse einen Konstruktor besitzen? (Probieren Sie es mit einem Testprojekt aus!)
 4. Kann eine Klasse verschiedene Konstruktoren besitzen?
 5. Was ist im Quader-Quelltext der Unterschied zwischen la und laenge?
 6. Ergänzen Sie in der Klasse 'Quader' ein Datenfeld rauminhalt und eine Methode public void
    berechneRauminhalt(), die aus laenge, breite und hoehe den Rauminhalt berechnet und in
    das Datenfeld rauminhalt einträgt. [Erläuterungen zu void folgen im nächsten Kapitel.]
 7. Testen Sie die Methode von Aufgabe 6, indem Sie eine Quaderinstanz vor und nach Ausführen
    dieser Methode untersuchen (inspizieren).
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
JAVA-Einführung, Seite 8

2. Zweites Projekt: Bankkonto (Bank_1)
In diesem Projekt werden wir eine Klasse 'Konto' erstellen. Dann werden zwei Instanzen dieser
Klasse erzeugt, die Girokonten darstellen sollen. Mit Hilfe geeigneter Methoden sollen
Einzahlungen und Abhebungen vom Girokonto möglich sein, aber auch Überweisungen von einem
Konto auf das andere.
Vorüberlegungen zur Klasse 'Konto'                              Modell der Klasse 'Konto':
Zunächst überlegen wir uns, welche Eigenschaften für Konto-   Klasse:
Instanzen in dieser Klasse festgelegt werden müssen: Ein            Konto
Konto besitzt auf jeden Fall eine Kontonummer, einen          Felder:
Kontoinhaber und einen Kontostand. Wir benötigen eine               ktoNummer (int)
Methoden zum Einzahlen, eine zum Abheben, eine zum                  ktoInhaber (String)
Überweisen. Aber auch zum Auslesen des Kontostands werden           ktoStand (double)
wir eine Methode verwenden. Diese Vorüberlegungen             Konstruktor:
(„Entwurf eines Modells“) sind von der Programmiersprache           Konto(ktoNr,ktoInh)
noch weitgehend unabhängig.                                   Methoden:
                                                                    einzahlen()
Erstellen des Konto-Projekts in BlueJ:                              abheben()
                                                                    getKontoStand()
Wir starten BlueJ und beginnen ein neues Projekt, dem wir den       überweisen(kto, betrag)
Namen Bank_1 geben (ein weiteres Bank-Projekt werden wir
dann Bank_2 nennen). Beachten Sie die Hinweise zur Readme.txt–Datei sowie zu den Kommentaren
vom ersten Beispiel.
Bei den Variablen (Datenfelder) lernen wir neue Datentypen kennen (bisher wurde nur int
verwendet): Der Typ double lässt zu, dass Zahlen mit Dezimalkomma (bzw. Dezimalpunkt) als
Wert zugewiesen werden können. Für den Kontoinhaber soll ein Name zugewiesen werden und
nicht eine Zahl oder Nummer. Hier wird der Typ String verwendet. Genau genommen ist String
gar kein Variablentyp, sondern eine Java-Klasse, damit wird auch der Großbuchstabe am
Wortanfang gerechtfertigt. In JAVA wird im Gegensatz zu einigen anderen Programmiersprachen
zwischen Groß- und Kleinbuchstaben unterschieden. Klassennamen beginnen üblicherweise immer
mit einem Großbuchstaben. Variablen- und Methodennamen beginnen üblicherweise mit einem
Kleinbuchstaben. Zur Verbesserung der Lesbarkeit werden bei Wortzusammensetzungen oft mitten
im Bezeichner Großbuchstaben verwendet (zum Beispiel getKontoStand ).
Die Datenfelder werden am Beginn der Klasse festgelegt (wie auch bei der Klasse 'Quader'). Der
einfachste Konstruktor könnte als Kontonummer und Kontostand jeweils den Wert 0 zuweisen, als
Kontoinhaber "" oder "dummy". Das ist für das Erzeugen mehrerer Konto-Instanzen natürlich nicht
sinnvoll – also wird man dafür sorgen, dass gleich beim Erzeugen einer Konto-Instanz nach dem
Namen und der Kontonummer gefragt wird. Der Kontostand kann mit 0 initialisiert werden, aber
auch die Kontoeinrichtung mit einem Startguthaben könnte vorgesehen werden.
'Konto' besitzt nach diesen Überlegungen 3 Datenfelder und 5 Methoden (eine davon ist der
Konstruktor), vergl. Kasten oben links. Es folgt der Quelltext für dieses Projekt (im folgenden
werden Quelltexte nicht als Screenshot dargestellt, sondern als Text mit Syntax-Hervorhebung; hier
außerdem mit Zeilenummern):
 1: /**
 2: * Es wird eine Klasse 'Konto' programmiert.
 3: *
 4: * @author B. Spier
 5: * @version 15.11.2009
 6: */
 7: public class Konto
 8: {   // Instanzvariablen (Datenfelder)
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
JAVA-Einführung, Seite 9

 9:     private int ktoNummer;
10:     private String ktoInhaber;
11:     private double ktoStand;
12:     /**
13:       * Konstruktor für Objekte der Klasse 'Konto'
14:       *
15:       * @param ktoNr   Parameter für Kontonummer
16:       * @param ktoInh Parameter für Kontoinhaber
17:       */
18:     public Konto(int ktoNr, String ktoInh)
19:     {    // Initialisieren der Datenfelder
20:          ktoNummer = ktoNr;
21:          ktoStand = 0;
22:          ktoInhaber = ktoInh;
23:     }
24:
25:     /**
26:       * Auslesen des Kontostands
27:       *
28:       * @return Wert des Kontostands
29:       */
30:     public double getKontoStand()
31:     {
32:          return ktoStand;
33:     }
34:
35:     /**
36:       * Einzahlung vornehmen
37:       *
38:       * @param betrag   Betrag der Einzahlung
39:       */
40:     public void einzahlen(double betrag)
41:     {
42:          ktoStand = ktoStand + betrag;
43:     }
44:
45:     /**
46:       * Auszahlung vornehmen, falls Kontostand ausreichend
47:       *
48:       * @param betr Betrag der Auszahlung
49:       */
50:     public void auszahlen(double betr)
51:     {
52:          if (ktoStand >= betr)
53:              einzahlen(-betr);
54:          else // Meldung ausgeben, wenn Konto nicht gedeckt:
55:              System.out.println("Das Guthaben reicht nicht aus!");
56:     }
57:
58:     /**
59:       * Überweisung auf ein anderes Konto vornehmen
60:       *
61:       * @param empfaenger Konto des Empfängers
62:       * @param geldBetrag Betrag der Überweisung
63:       */
64:     public void ueberweisen(Konto empfaenger, double geldBetrag)
65:     {
66:          auszahlen(geldBetrag);
67:          empfaenger.einzahlen(geldBetrag);
68:     }
69: }

Auf die Eigenschaft private der Instanzvariablen dieser Klasse wird auf Seite 15 eingegangen.
Es werden jetzt die 5 Methoden der Klasse 'Konto' erläutert:
   1. Die Methode Konto ist ein Konstruktor, denn sie heißt genauso wie die Klasse. Sie trägt die
      als Parameter übergebenen Werte in die Datenfelder der jeweiligen Instanz ein.
JAVA Einführung in die Programmiersprache - BlueJ unter Verwendung der Entwicklungsumgebung
JAVA-Einführung, Seite 10

    2. Mit der Methode getKontoStand wird der aktuelle Kontostand ausgelesen.
    3. Die Methode einzahlen hat keinen Rückgabewert, deshalb muss sie mit dem reservierten
       Wort void deklariert werden.
       Beim Einzahlen eines Betrages wird der Kontostand um diesen Betrag erhöht. Bei der
       Schreibweise ktoStand = ktoStand + betrag muss man sich klar machen, dass es sich
       nicht um eine Gleichung handelt, sondern um eine Wertzuweisung: Zuerst wird der Wert
       von ktoStand + betrag ermittelt, dann wird dieser wieder dem Datenfeld ktoStand
       zugewiesen.
       Die Schreibweise ist professionellen Programmierern noch zu umständlich, deshalb ist auch
       die kürzere – aber besonders für den Anfänger erheblich schwerer lesbare – Schreibweise
       zugelassen, die dasselbe bewirkt: ktoStand += betrag
    4. Das Auszahlen entspricht dem Einzahlen eines negativen Betrags, deshalb kann man die
       Methode zum Einzahlen verwenden. Hier im Beispiel wurde einmal angenommen, dass man
       das Konto nicht überziehen darf; falls man mehr abheben möchte als der Kontostand beträgt,
       wird eine entsprechende Meldung ausgegeben. Der Vergleichsoperator >= steht für größer
       oder gleich. Die weiteren sind
JAVA-Einführung, Seite 11

Wenn Programmierer Java-Klassen austauschen oder weitergeben, geben sie in der Regel auch die
Dokumentation mit. Die Klassen können als Quelltext (Datei mit der Extension „.java“) oder als
compilierte Klasse (Extension „.class“) weitergegeben werden. Sie finden diese Dateien, wenn Sie
mit dem Windows-Explorer den Ordner aufsuchen, in dem Sie Ihr Projekt gespeichert haben.
Die Dokumentation zeigt Ihnen außer den Bezeichnungen der öffentlichen Methoden auch die
Bedeutung der Kommentare, die Sie mit '/**' eingeleitet haben: Sie finden nicht nur die Kom-
mentare zu den Methoden in der Method Summary wieder, sondern bei der differenzierten
Beschreibung der einzelnen Methoden (weiter unten) auch die Bedeutung der Parameter (siehe
@param) oder die Bedeutung des Rückgabewerts (siehe @return) der Methode getKontostand.
Klicken Sie in der Constructor Summary auf den Klassenbezeicher 'String': Sie werden auf eine
völlig gleichartig aufgebaute Webseite geführt, welche die Klasse 'String' beschreibt. Auf diesen
Typ von Webseiten trifft man (fast) immer, wenn man Erklärung zu JAVA-Klassen sucht.
Kommentare, die dagegen mit // eingeleitet wurden (einzeilige Kommentare), sind als Notizen
aufzufassen, die der Programmierer für sich selbst (oder einen Leser des Quelltextes) angefertigt
hat. Das gilt auch für die mehrzeiligen Kommentare, die zwischen '/*' und '*/' stehen.
Fragen und Aufgaben zum Text
10. Untersuchen Sie, wie sich die Dokumentation der Klasse ändert, wenn Sie vor einem der
    Datenfelder das Schlüsselwort private durch public ersetzen! (Siehe auch Seite 15.)
11. Untersuchen Sie, wie sich die Dokumentation der Klasse ändert, wenn Sie vor einem der
    Datenfelder das Schlüsselwort private (bzw. public) entfernen (machen Sie dies anschließend
    für die weitere Verwendung des Projekts rückgängig!). Testen Sie auch den Shortcut Strg-j.
Dieses Beispiel hat gezeigt, dass Instanzen auch auf Methoden anderer Instanzen zugreifen können:
Beim Überweisen ruft das überweisende Konto die Methode einzahlen des empfangenden Kontos
auf. Die Syntax dafür erfordert die Angabe des Objekts, dessen Methode aufgerufen werden soll,
sowie den Namen der Methode – als Trennzeichen steht dazwischen ein Punkt.
Es mag als unbefriedigend erscheinen, dass beim Überweisen von einem Konto auf ein anderes
jeweils der Name des Kontos eingegeben werden muss, und dass es hier nicht über die Eingabe der
Kontonummer geht. Die Ursache liegt darin, dass es kein „übergeordnetes“ Objekt gibt, das die
Fähigkeit besitzt, aus der Kontonummer zu ermitteln, welche Kontoinstanz dazu gehört. Wenn man
bei einer Überweisung eine Kontonummer als Parameter übergeben möchte, müssten alle vorhan-
denen Kontoinstanzen daraufhin durchsucht werden, ob sie die betreffende Kontonummer besitzen.
Wenn das Konto nicht gefunden wird, muss die Überweisung abgelehnt werden.
Dieser anspruchsvollen Aufgabe widmet sich das folgende Kapitel.

3. Drittes Projekt: Bank_2
Legen Sie ein neues Projekt mit dem Namen 'Bank_2' an. Dieses Projekt verwendet wieder eine
Klasse 'Konto', dessen Quelltext fast vollständig mit dem des vorigen Projekts übereinstimmen
wird. Klicken Sie nicht auf „Neue Klasse“, sondern wählen Sie im Menü „ Bearbeiten / Klasse aus
Datei hinzufügen ...“! So können Sie aus Bank_1 die Klasse „Konto“ ins Projekt Bank_2 kopieren.
Bearbeiten Sie jetzt in 2 Punkten den Quelltext dieser Klasse:
Als erstes löschen Sie die Methode ueberweisen der Klasse 'Konto' im Projekt Bank_2, denn
Überweisungen wird die noch zu erstellende Klasse 'Bank' übernehmen.
Die Klasse 'Konto' benötigt aber noch eine kurze Methode getKontoNummer():
    public int getKontoNummer()
    {
        return ktoNummer;
    }
Ergänzen Sie diese Methode, gern auch mit den Kommentaren für die Dokumentation!
JAVA-Einführung, Seite 12

Anschließend erstellen wir eine weitere Klasse in diesem
Projekt mit dem Namen 'Bank' – dies wird damit unser erstes Modell der Klasse 'Bank':
Projekt, in dem wir zwei Klassen definieren.                       Klasse
Die Konten, die im Bankmodell verwaltet werden sollen,                   Bank
müssen in irgendeiner Form gespeichert werden. JAVA stellt         Felder:
dafür die Klasse ArrayList zur Verfügung. Instanzen dieser               Liste der Konten
                                                                   Konstruktor
Klasse sind Listen-Objekte, sie besitzen Methoden zum                    Bank()
Verwalten der Listenelemente. Die wichtigste ist die zum Methoden
Hinzufügen. Natürlich kann eine solche Liste eingetragene                neuesKonto()
Elemente auch wieder löschen, eine „Kontoauflösung“ ist aber             einzahlen()
hier bei unserem Bankmodell nicht vorgesehen. Damit solche               abheben()
Listen-Objekte vielseitig sind, verwalten sie nur Zeiger auf die         getKontoStand()
eingetragenen Elemente, aber keine Information darüber, von              ueberweisen()
welchem Typ die eingetragenen Elemente sind. Die Liste merkt
sich also in unserem Beispiel nicht, ob ein Konto oder ein Quadrat eingetragen ist – die
Konsequenzen zeigen sich, wenn man ein Element aus der Liste verwenden will (s.u.).
Der Quelltext der Klasse 'Bank' wird nun in Abschnitten erläutert:
   1: import java.util.*; // macht ArrayList verfügbar!
   2: /**
   3: * Die Klasse Bank kann in einer Liste mehrere Konten verwalten,
   4: * zwischen denen Überweisungen ausgeführt werden können.
   5: *
   6: * @author B.Spier
   7: * @version 17.11.09
   8: */
   9: public class Bank
  10: {
  11:       // einzige Instanzvariable
  12:       private ArrayList kontoListe;
  13:
  14:       /**
  15:         * Konstruktor für Objekte der Klasse Bank
  16:         */
  17:       public Bank()
  18:       {
  19:            // Instanzvariable initialisieren
  20:            kontoListe = new ArrayList();
  21:       }
Da ArrayList nicht ein gewöhnlicher Typ wie z.B. int ist, sondern eine Klasse, muss  von dieser
Klasse erst eine Instanz (kontoListe) erzeugt werden, bevor sie verwendet werden     kann. Das
geschieht mit der Zeile 20 im Konstruktor für das Bankobjekt: Hier wird der Konstruktor von
ArrayList aufgerufen. Diese Syntax (new ...) haben Sie vielleicht auch schon bei der Erzeugung
der Quadrate oder Konten „von Hand“ bei BlueJ bemerkt.
  22:       /**
  23:         * Einrichten eines neuen Kontos:
  24:         * Es ist kein Parameter für den Inhaber vorgesehen, weil das Testen
  25:         * des Programms dann einfacher ist. Alle Konten gehören "Meier"!
  26:         * @param kontoNr für die Kontonummer
  27:         */
  28:       public void neuesKonto(int kontoNr)
  29:       {
  30:            Konto neuKto;                  // Variable neuKto vom Typ Konto
  31:            neuKto = new Konto(kontoNr,"Meier"); // Konto-Objekt erzeugen
  32:            kontoListe.add(neuKto); // Konto in die Liste eintragen
  33:       }
JAVA-Einführung, Seite 13

Anders als im vorigen Beispiel werden neue Konten jetzt nicht mehr durch BlueJ nach Rechtsklick
auf das Klassensymbol für 'Konto' erzeugt, sondern durch die Methode neuesKonto eines
Bankobjekts. Wir müssen also erst ein Bankobjekt erzeugen, dann können wir nach Rechtsklick auf
das Objektsymbol dessen Methode neuesKonto() aufrufen, die den Konstruktor der Klasse 'Konto'
verwendet. Das neu erzeugte Konto – besser eine Referenz darauf (auch „Zeiger“ genannt) – wird
dann mit add in die Liste eingetragen. Eine Bankinstanz verwaltet so jedes erzeugte Konto in seiner
Liste der Konten.
  35:       /**
  36:         * Suchen des Konto-Objekts an Hand seiner Kontonummer
  37:         *
  38:         * @param     num für die Kontonummer
  39:         * @return Referenz auf das (hoffentlich!) gefundene Konto(-Objekt)
  40:         */
  41:       private Konto findByNumber(int num)
  42:       {
  43:            int i;                  // Zähler für die Schleife, Referenzen
  44:            Konto einKto, dasKto; // Zeiger für laufendes bzw. gefundenes Kto.
  45:                                    // (in der Schleife benötigte Variablen)
  46:            i = 0;                  // Initialisierung für die Schleife
  47:            dasKto = null;          // Null-Zeiger, steht für ungültiges Konto
  48:            while (i < kontoListe.size()) // Schleifenkopf
  49:            {                       // Alle Konten in der Liste werden geprüft.
  50:                 einKto = (Konto) kontoListe.get(i); // Ein Konto aus der Liste
  51:                 if (einKto.getKontoNummer() == num) // KtoNr. prüfen
  52:                      dasKto = einKto;                 // hier: Konto gefunden!
  53:                 i++;                                  // entspricht i = i + 1;
  54:            }
  55:            if (dasKto == null)
  56:              System.out.println("ungültige Kontonummer!");
  57:            return dasKto;       // Referenz auf das gefundene Konto (oder null)
  58:       }
Mit Hilfe der Methode findByNumber kann das Bankobjekt alle Konten, die in die Liste
eingetragen sind, nach der Kontonummer durchsuchen. Wir verwenden hier eine while-Schleife,
weil dies die einfachste Schleifenprogrammierung ist; die Kommentare erklären schon fast alles:
Wenn in der Liste z.B. 5 Konten eingetragen sind, wird die Schleife 5-mal durchlaufen, wobei i
nacheinander die Werte 0, 1, …, 4 annimmt. Die Schleife wird auch dann 5 mal durchlaufen, wenn
das gesuchte Konto schon früher gefunden wurde – das ist zwar keine optimale Programmierung,
erlaubt aber eine leicht verständliche Form unserer ersten Schleife (mehr zu while s.S. 39).
Zeile 50: Weil die Liste mit get(i) nur einen untypisierten Zeiger auf das Listenelement am Platz i
zurück gibt, muss dieser vor der Zuweisung an die Variable einKonto eine Typumwandlung
erfahren. Das geschieht durch das vorangestellte (Konto) – der Fachmann spricht dabei von einem
„Cast-Operator“. Eine unpassende Typumwandlung kann schlimme Fehler verursachen, deshalb
gibt es beim Übersetzen eine Warnmeldung! (Ergänzende Information siehe Anhang, Seite 41)
Die Methoden einzahlen und abheben verwenden diese Methode findByNumber:
  60:       /**
  61:         * Einzahlen auf ein Konto unter Angabe der Parameter
  62:         *
  63:         * @param kontoNr für die Kontonummer
  64:         * @param betrag für den Geldbetrag
  65:         */
  66:       public void einzahlen(int kontoNr, double betrag)
  67:       {
  68:            Konto dasKonto;
  69:            dasKonto = findByNumber(kontoNr);
  70:            if (dasKonto != null) dasKonto.einzahlen(betrag);
  71:       }
JAVA-Einführung, Seite 14

Zeile 70 prüft, ob überhaupt eine Konto mit der angegebenen Nummer gefunden wurde: In JAVA
steht das Ausrufezeichen für die Negation, != heißt also „ungleich“. Die if-Anweisung ist hier ohne
else verwendet worden. Bei ungültiger Kontonummer wurde ein Hinweis bereits von
findByNumber ausgegeben. Weil die Anweisung in Zeile 70 bzw. 83 so kurz ist, wird auf den sonst
bei if-Anweisungen üblichen Zeilenumbruch verzichtet.
  73:       /**
  74:         * Abheben von einem Konto unter Angabe der Parameter
  75:         *
  76:         * @param kontoNr für die Kontonummer
  77:         * @param betrag für den Geldbetrag
  78:         */
  79:       public void abheben(int kontoNr, double betrag)
  80:       {
  81:            Konto dasKonto;
  82:            dasKonto = findByNumber(kontoNr);
  83:            if (dasKonto != null) dasKonto.auszahlen(betrag);
  84:       }
Abrufen des Kontostands (können Sie eine Prüfung auf gültige Kontonummer ergänzen?):
  86:       /**
  87:         * Abrufen des Kontostands unter Angabe der Kontonummer
  88:         *
  89:         * @param kontoNr für die Kontonummer
  90:         * @return Kontostand
  91:         */
  92:       public double kontostandAbrufen(int kontoNr)
  93:       {
  94:            Konto dasKonto = findByNumber(kontoNr);
  95:            return dasKonto.getKontoStand();
  96:       }
Haben Sie  bemerkt, dass die Deklaration einer Variablen (dasKonto) und die Zuweisung    an diese
in einem einzigen Schritt erfolgen kann? Hier wird der Zeiger auf das gefundene Konto zugewiesen.
Nun zur Methode zum Überweisen von einem Konto auf ein anderes:
  98:       /**
  99:         * Überweisen unter Angabe der Parameter
 100:         *
 101:         * @param ktoNrA Konto des Absenders
 102:         * @param ktoNrB Konto des Empfängers
 103:         * @param betrag Betrag der Überweisung
 104:         */
 105:       public void ueberweisen(int ktoNrA, int ktoNrB, double betrag)
 106:       {
 107:            Konto empf, absd; // Konto-Objekte
 108:            absd = findByNumber(ktoNrA);
 109:            empf = findByNumber(ktoNrB);
 110:            if ((absd != null) & (empf != null))
 111:            {
 112:                absd.auszahlen(betrag);
 113:                empf.einzahlen(betrag);
 114:            }
 115:       }
 116: }
Hier muss die Gültigkeit beider Kontonummern geprüft werden. Nur wenn Absender-Konto absd
und Empfänger-Konto empf gültig sind, wird die Überweisung ausgeführt. Die logische UND-
Verknüpfung wird in JAVA durch das &-Zeichen dargestellt. Da im WENN-Fall zwei Anweisungen
stehen, sind geschweifte Klammern zur Kennzeichnung von Anfang und Ende des Blocks
erforderlich. Dasselbe gilt auch für den SONST-Fall, wenn er aus mehreren Anweisungen besteht.
JAVA-Einführung, Seite 15

(Die Klammern dürfen selbstverständlich auch gesetzt werden, wenn sie nur eine einzige Anwei-
sung einschließen).
Wenn sich der Quelltext für die Klasse 'Bank' fehlerfrei übersetzen ließ, können wir jetzt unser
Bankinstitut eröffnen und Kundenkonten einrichten, um
die von uns programmierten Klassen und deren
Instanzen zu testen! Also: Bankinstanz mit Rechtsklick
erstellen, Bank-Namen wählen (z.B. "JGiro", "DieBank"
o.ä.) und dann in dieser Bank mindestens 2 Konten
einrichten. Nach einer Einzahlung sollte dann auch eine
Überweisung möglich sein.
Die Klasse 'Konto' wird jetzt nicht mehr von uns,
sondern nur von dem Bank-Objekt benutzt. Diese
Beziehung „Bank verwendet Konto“ (allgemein
„ verwendet “) stellt BlueJ
durch einen gestrichelten Pfeil in der Projektübersicht
dar.
Fragen und Aufgaben zum Text
12. Ergänzen Sie in einem der Bank-Projekte eine Methode, die zur Kontonummer den Namen des
    Kontoinhabers zurück gibt.
13. Ein Objekt A soll die Methode tuIrgendWas() eines Objekts B aufrufen. Wie ist der Aufruf zu
    schreiben?
14. Im Projekt Bank seien zwei Instanzen erzeugt: HASPA und DEUTSCHE_BANK. Mit beiden
    Instanzen wurden mehrere Konten erzeugt. Welche Überweisungen sind möglich?
Informationen zu private und public
Bisher wurden alle Datenfelder als private deklariert. Das ist üblich, wenn keine fremde Instanz
direkten Zugriff auf den Wert einer solchen Variablen zu haben braucht.
Stellen wir uns vor, von der Klasse 'Konto' haben wir keinen eigenen Quelltext, sondern nur die
compilierte Klassendatei und die Dokumentation. Wir erstellen eine Klasse 'Bank', welche
Instanzen der Klasse 'Konto' verwalten soll. Dadurch, dass ktoStand als private deklariert ist,
kann nur über öffentliche Methoden (getKontoStand, auszahlen, einzahlen) auf den Kontostand
zugegriffen werden. Der Programmierer der Klasse 'Konto' könnte diese Methoden so erweitern,
dass erst eine Geheimnummer eingegeben werden muss, bevor der Kontostand ausgelesen oder eine
Auszahlung/Überweisung vorgenommen werden kann. Methoden, die den Kontostand ändern,
könnten auch jeweils einen Text ausgeben, der einem Kontoauszugs-Eintrag entspricht. Wäre
ktoStand jetzt public, so könnten wir in der Klasse 'Bank' die folgende Methode programmieren,
die eine Berechtigungsprüfung umgeht, indem sie auf den Kontostand direkt zugreift:
    public void ueberweisen(int ktoNrA, int ktoNrB, double betrag)
    {
        Konto empf, absd; // Konto-Objekte
        absd = findByNumber(ktoNrA);
        empf = findByNumber(ktoNrB);
        if ((absd != null) & (empf != null))
        {
            absd.ktoStand -= betrag; // Kontostand verringern
            empf.ktoStand += betrag; // Kontostand erhöhen
        }
    }
Nicht nur Variablen, auch Methoden können private oder public sein. Unsere Klasse Bank
benötigt die Methode findByNumber, die wir aber beim simulierten Zahlungsverkehr mit der Maus
im BlueJ-Fenster nie aufzurufen brauchen und deshalb als private deklariert haben.
JAVA-Einführung, Seite 16

Hätten wir sie als public deklariert,
wäre die Auswahl der möglichen
Methoden beim Rechtsklick auf ein
Bankinstanzsymbol um eine unnötige
Zeile unübersichtlicher geworden, wie
die Abbildung zeigt.
Grundsätzlich sollten also nur die Me-
thoden und Datenfelder öffentlich sein,
auf die der Zugriff „von außen“
tatsächlich benötigt wird.

4. Viertes Projekt:
   Fahrkartenautomat
Mit diesem Projekt testen Sie sich, wie weit Sie eigenständig (nach wenigen Vorgaben)
programmieren können. Fast alles, was Sie benötigen, wurde in den bisherigen Kapiteln genannt:
   • Namen für das Projekt festlegen (also einen Ordner einrichten),
   • neue Klasse erzeugen (wieder einen Namen überlegen),
   • private Datenfelder deklarieren, diese mit dem Konstruktor initialisieren,
   • weitere Methoden programmieren (siehe folgende Punkte 1, 2, 3, 5).
Orientieren Sie sich dabei an den bisher erstellten Programmen!
Unser virtueller Fahrkartenautomat soll folgendes können:
1. Der Anwender muss einen Fahrpreis für die gewünschte Fahrkarte eingeben können
     (Festlegung des zu zahlenden Betrags, z.B. 4.3 für 4,30€), die Klasse benötigt dafür eine
     sinnvoll benannte Methode. Ein Datenfeld fahrPreis vom Typ double muss dann den
     gewünschten Fahrpreis speichern. Zum Testen des Automaten ist es zweckmäßig, bereits im
     Konstruktor den Fahrpreis mit z.B. 3.8 zu initialisieren – dann muss man nicht bei jedem
     Neustart erst einen Fahrpreis eingeben.
2. Der Anwender muss nach der Festlegung des Fahrpreises „Geld einwerfen“ können (z.B.
     mehrmals 1€ oder 0,50€ o.ä.), eine Prüfung auf tatsächlich möglichen Münzwert entfällt. Die
     Klasse benötigt im Prinzip also eine Methode einzahlen(betrag) wie im vorigen Projekt.
     Ein weiteres Datenfeld einwurf vom Typ double muss den bereits gezahlten Betrag
     speichern.
3. Eine Methode druckeFahrkarte soll einen von der bisherigen Zahlung abhängigen Text aus-
     geben: Zuerst wird der gewählte Fahrpreis „ausgedruckt“, dann der bisher gezahlte Betrag.
     Wenn dieser noch nicht reicht, wird der Fehlbetrag ausgegeben. Wurde genug gezahlt, ist der
     Kauf abgeschlossen, und die Höhe des Wechselgeldes wird ausgegeben. Außerdem muss der
     eingeworfenen Betrag auf 0 zurückgesetzt werden. Info zum „Drucken“:
     System.out.println (print line) System.out.println("BlueJ-Bahngesellschaft");
     gibt eine Zeile, also Text mit an- System.out.print("Fahrkahrte zu ");            // Text
     schließendem Zeilenumbruch aus.       System.out.println(fahrPreis);              // Wert
                                           ... (u.s.w.)
     Neu ist hier: System.out.print
     (ohne ln) gibt Text aus, ohne dass sich ein Zeilenumbruch anschließt. Sie können die beiden
     letzten Zeilen aber auch zu einer einzigen zusammenfassen:
      System.out.println("Fahrkarte zu " + fahrPreis);
     Mit + können Strings aneinander gehängt werden, in diesem Fall wandelt JAVA die Zahl
     fahrPreis dazu in einen String um.
4.   Diesen Punkt können Sie ergänzen, nachdem alles andere fehlerfrei läuft:
JAVA-Einführung, Seite 17

     Die Klasse soll ein drittes Datenfeld gesamtEinnahmen besitzen, in dem die Einnahmen bei
     jedem Kauf eines Fahrscheins aufsummiert werden. Es genügt, dass dieses Datenfeld durch
     „Inspizieren“ geprüft werden kann – oder möchten Sie eine Methode getGesamteinnahmen()
     schreiben?
5. Optional können Sie den Fahrkartenautomaten verbessern, indem Sie eine Methode zum
     Abbrechen des Fahrkartenkaufs ergänzen. Sie sollte als Text die Rückzahlung des bisher
     eingeworfenen Betrags melden. Was muss sie sonst noch tun?
Die Abbildung zeigt ein
mögliches Ergebnis des
Projekts: Sie können den
Namen des Projekts, den
Namen der Klasse und den
aktuell gewählten Namen
für die Instanz dieser Klasse
herauslesen.
Ein Fahrpreis wurde fest-
gelegt, Geld wurde „einge-
worfen“.
Das Bild zeigt das Fenster
nach Aufruf der Methode
druckeFahrkarte.
Mit Sicherheit wird Ihr Ergebnis noch nicht so
wie hier aussehen können, denn hier wurde die
Ausgabe auf 2 Nachkommastellen und mit
Dezimalkomma formatiert. Diese Formatierung rundet zugleich, so dass Rechenfehler ausgeglichen
werden. Es folgen hierzu weitere Informationen:
Wie entstehen Rechenfehler beim Computer?
                                                 1   1   1   5
Computer rechnen im Zweiersystem. Brüche wie 2 , 4 , 8 , 8 sind in diesem System abbrechende
Dualbrüche. Brüche, deren Nenner jedoch keine Zweierpotenz sind, sind periodische Dualbrüche.
Der Grund ist der, den wir aus dem Dezimalsystem kennen: Wenn der Nenner sich nicht aus
Potenzen von 2 oder 5 zusammensetzt, wird der Dezimalbruch periodisch. 2 und 5 sind Teiler der
                           3   3    12                     4
Basis 10, daher ist z.B. 25 = 5 = 100 =0,12 abbrechend. 11 =0, 36 ist dagegen periodisch. Da die
                              2

Basis 2 nur die 2 als echten Teiler hat, können im Zweiersystem nur Brüche wie die oben genannten
                   1         1
abbrechend sein, 5 oder 10 sind in diesem System dagegen periodisch, also unendlich lang. Da
der Computer aber Zahlen nur in wenigen Bytes speichert, muss er die Darstellung abbrechen.
Selbst wenn dabei richtig gerundet wird, entstehen Ungenauigkeiten. Die Ungenauigkeit zeigt sich
beim Fahrkartenautomaten z.B. bei einem Fahrschein zu 3,80€, wenn 0,10€ bezahlt sind. Als
Restbetrag werden 3,699999999999997€ berechnet! (Probieren Sie es aus!)
Zahlen formatieren
JAVA stellt verschiedene Methoden zum Formatieren von Zahlen zur Verfügung. In JAVA sind alle
Methoden an Klassen gebunden, wir verwenden hier die Methode format der Klasse String.
   String.format("Noch zu zahlen: %.2f €",(fahrPreis – einwurf))
liefert einen formatierten String für den Wert von (fahrPreis – einwurf), er
                                                                         enthält am Beginn
den Text „Noch zu zahlen: “. Das %-Zeichen kennzeichnet das Einfügen aus nachfolgend
angegebenen Parametern. „.2“ kennzeichnet die Genauigkeit von 2 Nachkommastellen, „f“
kennzeichnet die Umwandlung eines float- oder double-Werts (Fließkommazahl). Die weiteren
Zeichen „ €“ folgenden dem eingefügten String, sodass das Ergebnis z.B. im Falle des Werts
JAVA-Einführung, Seite 18

0.1999999994 der String „Noch zu zahlen: 0,20 €“ wird, weil die Methode zugleich auch rundet.
Die Umwandlung des Dezimalpunkts in ein Komma erfolgt auf Grund der Spracheinstellung des
Betriebssystems.
Die format-Methode der Klasse String ist sehr vielseitig, mit ihr können z.B. auch Datumswerte
formatiert werden (siehe nachfolgendes Kapitel). Ein weiteres Beispiel für die Formatierung auf 2
Nachkommastellen:
       System.out.println(String.format("Fahrkahrte zu %.2f €",fahrpreis));
Diese Art der Formatierung können Sie überall dort verwenden, wo ein Euro-Wert mit 2
Nachkommastellen ausgeben werden soll.

5. Fünftes Projekt: Person (Vererbung / GregorianCalendar)
Ein bedeutendes Merkmal objektorientierter Programmierung (und darum geht es bei JAVA) ist die
Möglichkeit, bereits programmierte Klassen als Ausgangsbasis für weitere Klassen mit zusätzlichen
Datenfeldern und Methoden zu verwenden. Die so von einer Basisklasse „abgeleiteten“ Klassen
erben die Datenfelder und Methoden der Basisklasse, wodurch der Quelltext der neuen Klasse
weniger umfangreich ist. Die Verwendung fertiger Basisklassen ist für den Programmierer eine
deutliche Arbeitserleichterung.
Dieses Prinzip werden wir in Kapitel 6 nutzen, um mit Hilfe bereits in JAVA vorgegebener Klassen
„Applets“ (Anwendungen) zu programmieren, die in einem Browser ablaufen können.
Erzeugen Sie das neue Projekt mit dem Namen „ Vererbung“. Erstellen Sie in diesem Projekt eine
Klasse mit der Bezeichnung Person. Eine Person hat einen Vornamen, einen Nachnamen, ein
Geburtsdatum. Außerdem soll
vermerkt werden können, ob
die Person Informatiker ist oder
nicht. Vor- und Nachname sind
Strings, das Geburtsdatum
müssen wir als Instanz der in
JAVA vordefinierte Klasse
GregorianCalendar festlegen
(die Bezeichnung bezieht sich
auf      den    Gregorianischen
Kalender, der seit dem 15.
Oktober 1582 regelt, welche
Jahre Schaltjahre sind). Die
Informatiker-Eigenschaft kann
nur die Werte true oder false
annehmen, dieser Typ heißt
boolean. Wenn eine Person
geboren wird, steht das
Geburtsdatum fest – darum
wird hier vorgeschlagen, dass
der Konstruktor beim Erzeugen
einer Instanz der Klasse Person
Tag, Monat und Jahr der Geburt
erfragt.
JAVA-Einführung, Seite 19

Wenn wir jetzt eine Instanz erzeugen, müssen wir also Werte für t, m, j eingeben. Da
GregorianCalendar die Monate als Zahlen von 0 bis 11 verwaltet, muss die Eingabe für m um 1
vermindert werden!
                                                           Beim Inspizieren der Person werden Sie
                                                           feststellen, dass Sie das Geburtsdatum
                                                           nicht in der Form von Tag, Monat und
                                                           Jahr auslesen können. Möchten Sie eine
                                                           Methode getGeburtsdatum() schrei-
                                                           ben, die dieses Datum als String zu-
                                                           rückgibt? Dazu müssen Sie heraus-
                                                           finden,      wie    aus    der    Instanz
                                                           geburtsDatum ein Datumsstring gewon-
                                                           nen werden kann! Sie müssen jetzt keine
                                                           Suchmaschine oder Foren bemühen,
holen Sie sich mit BlueJ (siehe Abb.) die Hilfe über Klassenbibliotheken! Sie führt auf die Webseite
         (Stand vom September 2014)
 http://docs.oracle.com/javase/7/docs/api/
                                                                   Sie finden dann in der
                                                                   Beschreibung der Klasse String
                                                                   etwas weiter unten die Beschrei-
                                                                   bung der beiden format-Metho-
                                                                   den.
                                                                   Klicken Sie wie in der Abbildung
                                                                   angedeutet auf „format“, von dort
                                                                   können Sie zu einer so umfang-
                                                                   reichen Beschreibung gelangen,
                                                                   wie ein „format string“ aussehen
                                                                   kann, dass Sie erleichtert sein
                                                                   dürften, einen Weg zur formatier-
                                                                   ten Ausgabe eines Datums auch
                                                                   im folgenden Absatz zu finden:
JAVA-Einführung, Seite 20

Die folgende Methode gibt das in geburtsDatum gespeicherte Datum formatiert als String zurück:
     public String getGeburtsdatum()
     {
         return String.format("%1$td.%1$tm.%1$tY", geburtsDatum);
     }
Vielleicht gelingt es Ihnen ja, mit Hilfe der angegebenen Webseite das Datum auch so zu
formatieren, dass zusätzlich noch der Wochentag ausgegeben wird (Aufgabe 22)!

Anmerkungen: Methoden, die Daten auslesen, beginnen üblicherweise mit get. Daran lehnt sich
hier der Vorschlag für den Methodennamen zum Auslesen des Geburtsdatums an. Wenn Sie solche
Sprachvermischungen vermeiden wollen, können Sie getDayOfBirth oder holeGeburtsdatum
verwenden. Ein Vorteil deutscher Wortanteile ist der, dass sofort erkennbar ist, ob vordefinierte oder
eigene Bezeichner verwendet sind.
Zur Übung – und damit unsere „Person“ etwas mehr zu vererben hat (darum geht es ja in diesem
Kapitel), folgen zunächst noch einige Aufgaben:
Fragen und Aufgaben zum Text
15. Wie ändert sich die formatierte Datumsausgabe, wenn Sie im format-String für das Jahr ein
    kleines „y“ verwenden?
16. Damit die Person einen Namen bekommt, wird eine Methode setName(String v, String n)
    benötigt, mit der Vor- und Nachname festgelegt werden. Schreiben Sie diese.
17. Schreiben Sie eine Methode setInfomatikerYes(), die das Datenfeld informatiker auf
    true setzt.
18. Schreiben Sie eine Methode setInfomatikerNo(), die informatiker auf false setzt.
19. Schreiben Sie eine Methode setInfomatiker(boolean x), die informatiker auf einen Wert
    setzt, den der Anwender eingibt.
20. Schreiben Sie eine Methode getGanzerName(), die die Kombination aus Vor- und Nachnamen
    als String zurück gibt.
21. Schreiben Sie eine Methode druckeGanzenNamen(), die mit System.out.println den
    vollständigen Namen auf das Konsolenfenster ausgibt. Diese Methode sollte getGanzerName
    verwenden!
22. Schaffen Sie es, das Geburtsdatum einschließlich Wochentag auszugeben?

Berechnung des Alters einer Person
Wir ergänzen jetzt noch eine Methode, die das Alter der Person liefert. Dafür brauchen wir eine
Instanz von GregorianCalender, die das aktuelle Datum enthält. Wir nennen sie heute und
erhalten sie, indem wir den Konstruktor ohne Parameter aufrufen. Dann schließt sich die
Berechnung des Alters an, die nicht ganz einfach ist, weil zunächst festgestellt werden muss, ob die
Person im laufenden Jahr bereits Geburtstag hatte (oder gerade hat). Die Verwendung einer
Hilfsvariablen hatteSchonGeburtstag macht den folgenden Quelltext (hoffentlich) leicht
verständlich:
JAVA-Einführung, Seite 21

public int getAlter()
{
    boolean hatteSchonGeburtstag = false; // wird nach Prüfung evt. true
    GregorianCalendar heute = new GregorianCalendar(); // Kalenderobjekt für
                                                         // heutiges Datum
    if (heute.get(Calendar.MONTH) > geburtsDatum.get(Calendar.MONTH))
                                          // Person hatte in diesem Jahr
         hatteSchonGeburtstag = true;     // schon Geburtstag. Weitere Prüfung
    else                                  // bei gleichem Monat:
         if (heute.get(Calendar.MONTH) == geburtsDatum.get(Calendar.MONTH)
               & heute.get(Calendar.DAY_OF_MONTH) >=
               geburtsDatum.get(Calendar.DAY_OF_MONTH)) // Tag vergleichen
             hatteSchonGeburtstag = true;
    if (hatteSchonGeburtstag)
         return heute.get(Calendar.YEAR) - geburtsDatum.get(Calendar.YEAR);
    else
         return heute.get(Calendar.YEAR) - geburtsDatum.get(Calendar.YEAR) - 1;
}

Vererbung
Jetzt sollen zwei weitere Klassen erstellt werden: Eine Klasse Schüler und eine Klasse Lehrer.
Da Schüler und Lehrer natürlich Personen sind, sollen auch sie Namen und Geburtsdatum besitzen.
Zusätzlich sollen Schüler aber ein Datenfeld für ihre Schulklasse (z.B. "11c", also vom Typ String)
besitzen. Lehrern geben wir keine Schulklasse, dafür aber zwei Unterrichtsfächer (weil das für die
meisten Lehrer am Gymnasium zutrifft).
Natürlich könnte man den Quelltext von Person kopieren, um alles zu übernehmen, und man
müsste nur die Klassenbezeichnung (Objektklasse, nicht Schulklasse – der Begriff „Klasse“ ist in
diesem Abschnitt leider nicht eindeutig!) im Konstruktor anpassen. Für den Zugriff auf
Unterrichtsfächer bzw. die Schulklasse wären noch wenige Methoden zu ergänzen. Dann hätten wir
aber einen großen Teil des Quelltextes 3 mal zu verwalten. Ein Fehler in der Berechnung des Alters
müsste in 3 Textdateien korrigiert werden. Um solche Nachteile zu vermeiden, wurde die
Möglichkeit geschaffen, von vorhandenen Klassen erweiterte Klassen abzuleiten. Die abgeleiteten
Klassen erben dann alle Eigenschaften und Methoden der Vorgängerklasse.
Zunächst erstellen wir in unserem Projekt eine neue
Klasse mit der Bezeichnung „Schüler“ (oder „Schueler“)
und eine weitere mit der Bezeichnung „Lehrer“.

Es gibt bei BlueJ zwei Verfahren, um diese Klassen als
Erweiterungen von Person zu deklariereren.

                                        Methode 1:
                                        Im BlueJ-Fenster wählen wir mit der Maus den Pfeil mit
                                        durchgezogener Linie aus und ziehen damit einen Pfeil von
                                        Lehrer zu Person.

                   Methode 2: Wir fügen in der    public class Schüler extends Person
                   Klasse Schüler die zwei        {
                   Wörter extends Person ein      ....  ...
                   (s. Abb.).                     }
Sie können auch lesen
NÄCHSTE FOLIEN ... Stornieren