Einführung in die Programmiersprache...

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

Transcript of Einführung in die Programmiersprache...

Einführung in dieProgrammiersprache

JAVA

unter Verwendung der Entwicklungsumgebung

BlueJ

Text von K.Spier (2004), überarbeitet von B.Spier (2009-2014)

JAVA-Einführung, Seite 2

Inhaltsverzeichnis

Kapitel 1: Vorstellung der Entwicklungsumgebung BlueJ und erstes Projekt ................................ 3Installation ..................................................................................................................................... 3Projekt Beispiel_1 (Quader) ........................................................................................................... 4Der Editor von BlueJ für JAVA-Quelltexte ...................................................................................... 5

Kapitel 2: Zweites Projekt: Bankkonto (Bank_1) ........................................................................... 8Erstellen einer vollständigen Übersicht zur Klasse 'Konto' (Dokumentation) ............................. 10

Kapitel 3: Drittes Projekt: Bank_2 ............................................................................................... 11Informationen zu private und public ........................................................................................... 15

Kapitel 4: Viertes Projekt: Fahrkartenautomat ............................................................................ 16Zahlen formatieren ..................................................................................................................... 17

Kapitel 5: Fünftes Projekt: Person (Vererbung / GregorianCalendar) ......................................... 18Vererbung .................................................................................................................................... 21Überschreiben von Methoden ...................................................................................................... 22

Kapitel 6: Sechstes Projekt: Wir programmieren ein Applet ........................................................ 24Aufbau 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 ................................................................. 32Klassenvariablen und Instanzvariablen ....................................................................................... 32Array ............................................................................................................................................ 33For-Schleife ................................................................................................................................. 34Start und Stop ............................................................................................................................. 34While-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 ....................................................................................................................................... 40JAVA-Programm ohne Entwicklungsumgebung erstellen ............................................................ 40Listen, die nur Instanzen einer einzigen Klasse verwalten............................................................ 41Formatierungen von numerischen Werten (2 Beispiele für String.format)..................................... 42

JAVA-Einführung, Seite 3

Vorbemerkung

Mit JAVA wurde eine objektorientierte Programmiersprache entwickelt, die unabhängig vomBetriebssystem des Computers ist, auf dem die Programme laufen. Es gibt viele so genannteEntwicklungsumgebungen, um JAVA-Programme zu erstellen. Eine Entwicklungsumgebung istzwar nicht Voraussetzung zum Programmieren – JAVA-Programme ließen sich auch mit einemeinfachen Texteditor erstellen. Mit einem Compiler können daraus Dateien erstellt werden, die einJAVA-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 auchkompiliert 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 Anhangeine kurze Beschreibung, wie man auch ohne Entwicklungsumgebung ein JAVA-Programmerstellen 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-Systemenjdk-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 wirdein 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. (SieheHomepage 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 suchtBlueJ die zu verwendende JAVA-Version und zeigt eventuell ein Auswahlfenster, wenn dieZuordnung nicht automatisch erfolgen kann.

Spracheinstellung: DeutschWenn die Entwicklungsumgebung in deutscher Sprache erscheinen soll, muss die Datei BlueJ.defsmit einem Text-Editor bearbeitet werden, geeignet ist z.B. WordPad (Startmenü/Zubehör). DieserEditor muss bei aktuellen Windows-Versionen als Administrator ausgeführt werden, damit imInstallationsordner (vermutlich: C:\Programme(x86)\BlueJ\) Schreibberechtigung erreicht wird.BlueJ.defs liegt im Unterverzeichnis lib des Installationsordners von BlueJ. Zum Öffnen muss alsDateityp „Alle Dokumente (*.*)“ eingestellt werden. In dieser Datei findet man (ungefähr Zeile 31) die Festlegung derSprache: Hier kann bluej-language=english in bluej.language=germangeändert werden. Danach wird die Datei gespeichert.

1 Aktuelle Version im August 20132 Aktuelle Version im August 2013

bluej.language=english

wird zu:

bluej.language=german

JAVA-Einführung, Seite 4

Ein Projekt beginnen: Projekt Beispiel_1

Wir starten BlueJ und wählen den MenüpunktProjekt/Neues Projekt.Es erscheint das Dialogfenster, in dem wir angeben,wo das Projekt gespeichert werden soll. Ein Projektbesteht immer aus mehreren Dateien, deshalb wirdfür jedes Projekt ein eigener Ordner angelegt.Ordner, die ein BlueJ-Projekt enthalten, werden vonBlueJ durch ein spezielles Symbol gekennzeichnet(siehe Abbildung).

Mit dem Schalter „Erzeugen“ wird der Ordner mitdem eingegebenen Namen angelegt und dieProjektdateien werden darin gespeichert. Die Arbeitsfläche von BlueJ enthält zunächst nurein Symbol für eine Readme-Datei, die für eineBeschreibung des Projekts vorgesehen ist. Nichtnur im Schulunterricht macht es Sinn, in einersolchen Datei eine ganz knappe Beschreibung desProjektes anzugeben. Die Datei wird mit einemDoppelklick auf das Symbol geöffnet, dannbearbeitet, gespeichert und wieder geschlossen.

Nun werden wir als erstes Beispiel eine Klassemit Namen 'Quader' erstellen (wie im Info-Kastenoben rechts).

Eine Klasse im Projekt erstellen

Wir klicken auf den Schalter Neue Klasse und geben als Namen fürdiese Klasse Quader ein. Daraufhin erscheint ein neues Symbol fürdiese Klasse in der Projektübersicht. Wir klicken doppelt auf diesesSymbol, um die Klasse zu bearbeiten. Zunächst sehen wir schon einige Zeilen vorgegebenen Textim Editor für unseren Java-Quelltext, den wir nach unseren Erfordernissen anpassen werden (einigeZeilen löschen, andere ergänzen).

Info:In der objektorientierten Programmierungarbeitet man mit Objekten. (logisch)Objekte können Eigenschaften haben.Beispiel:Ein Quader hat die Eigenschaften Länge, Breite, Höhe. Diesen Eigenschaften können verschiedene Werte zugeordnet sein. Ein 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 Definition einer Klasse wird der Objekt-Typ beschrieben, und das danach konstruierte Objekt wird auch als Objekt-Instanz bezeichnet.

JAVA-Einführung, Seite 5

Der Editor von BlueJ für JAVA-Quelltexte

Der Editor arbeitet mitsogenannter Syntax-Hervorhebung, d.h.dass z.B. reservierteWörter oder Kom-mentare in bestimmterWeise farblich hervor-gehoben werden.

Die Tatsache, dass hierder größte Teil desTextes in blau dar-gestellt ist, zeigt bereits,wie wichtig Kommen-tare in Computerpro-grammen sind.Bei genauem Hinsehenkönnen wir sogar zweiverschiedene Arten vonKommentaren unter-scheiden:

Einfache Kommentarewerden mit zweiSchrägstrichen einge-leitet und dienen oftdem Programmierer alsNotiz.Die anderen, die mit/** eingeleitet, mit *fortgesetzt und mit */beendet werden, dienenzusätzlich zur Informa-tion für andere – daraufwird später näher einge-gangen (Seite 10). Aufdie Begriffe public undprivate wird ebenfallsspäter eingegangen(Seite 15). Wir sehen,dass die Klassendefi-nition mit dem Wortclass eingeleitet wird,gefolgt vom Namen derKlasse.

Dann folgt eine öffnende geschweifte Klammer, die zugehörige schließende Klammer steht in derletzten 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, Seite 6

Zum Aufbau dieses Programm-Quelltextes:Nach dem Klassennamen werden im obigen Beispiel die Eigenschaften (hier: Variablen) für dieInstanzen festgelegt: Jede Instanz, die wir gemäß diesem „Bauplan“ erzeugen, soll je eine Variablefür Länge, Breite und Höhe besitzen. Der Variablentyp wird in JAVA immer dem Variablennamenvorangestellt. Hier wird int als Variablentyp angegeben, d.h. die aufgeführten Variablen sind vomTyp „integer“, sie können nur ganzzahlige Werte aufnehmen. (Wir folgen damit dem Vorschlag vonBlueJ für die Variablentypen, andere lernen wir später kennen.).

Da diese Variablen hier den Instanzen zugeordnet sind, heißen sie auch Objektfelder oderDatenfelder 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ührenMethodenaufrufe 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 JAVAimmer mit dem Namen der Klasse überein. Dieser Konstruktor ist hier sehr einfach aufgebaut: Erlegt 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, dieLänge und die Breite. Für die Zuweisung von Werten an eine Variable wird in JAVA ein einfachesGleichheitszeichen verwendet (wie in BASIC, C++, aber anders als in PASCAL u. DELPHI). Auchfür den Konstruktor werden Anfang und Ende durch öffnende bzw. schließende geschweifteKlammer gekennzeichnet. Beachten Sie die übersichtlichen Positionen aller {}-Klammerpaare!

Das Beispiel zeigt außerdem, dass eine Klasse mehrere Konstruktoren besitzen kann: Ein zweiterKonstruktor dient dazu, Quader zu konstruieren, bei denen mit Aufruf des Konstruktors Werte fürdie 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 Methodenbesitzen kann, hier zur Berechnung des Volumens. Diese Methode berechnet aus Länge, Breite undHöhe der Quader-Instanz ihr Volumen. Durch die Angabe von return wird festgelegt, welcher Wertbei 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ückgabewertesangegeben 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 wirddieser 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 fehlendeKlammer, ein fehlendes Semikolon oder ähnliches.

Nach dem Kompilieren der Klasse 'Quader' werden wir mit Hilfe von BlueJ Instanzen zu dieserKlasse erzeugen und untersuchen.

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 werdenaber 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.

JAVA-Einführung, Seite 7

Instanzen der Klasse Quader erzeugen

Wenn die Klasse 'Quader' erfolgreich com-piliert wurde, ist das Symbol für dieseKlasse nicht mehr schraffiert. Um nun eineInstanz von dieser Klasse zu erzeugen,klicken wir mit der rechten Maustaste aufdas Klassensymbol. Aus dem sich öffnen-den Kontextmenü wählen wir zunächst newQuader() aus. Der (Standard-) Konstruktorwird ausgeführt, nachdem wir einen Namenfür die Instanz festgelegt haben. Auf demHauptfenster erscheint unten ein Symbolfür das soeben erzeugte Objekt. Wir könnenden Vorgang wiederholen und somit wei-tere Instanzen derselben Klasse erzeugen.

Wählen wir das nächste Malaus dem Kontextmenü newQuader(la,br,ho) aus, so werdenwir zum Ausführen deszweiten Konstruktors nachden Werten für die Parameterla, br und ho gefragt: Imoberen Abschnitt desDialogfensters wird der Kom-mentar angezeigt, der imQuelltext dem Konstruktorvorangestellt worden war.Klicken wir nun mit der rech-ten Maustaste auf ein rotesObjektsymbol, so können wiru.a. aus dem Kontextmenüauswählen, ob wir das Objekt löschen oderuntersuchen (inspizieren) wollen. Das Inspi-zieren zeigt uns, welche Werte die Variablenlaenge, breite und hoehe besitzen. Außerdemkönnen wir über das Kontextmenü die Methode zur Volumenberechnung aufrufen. (Dort gezeigtegeerbte Methoden interessieren an dieser Stelle nicht.)

Fragen und Aufgaben zum Text1. 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, Seite 8

2. Zweites Projekt: Bankkonto (Bank_1)In diesem Projekt werden wir eine Klasse 'Konto' erstellen. Dann werden zwei Instanzen dieserKlasse erzeugt, die Girokonten darstellen sollen. Mit Hilfe geeigneter Methoden sollenEinzahlungen und Abhebungen vom Girokonto möglich sein, aber auch Überweisungen von einemKonto auf das andere.

Vorüberlegungen zur Klasse 'Konto'

Zunächst überlegen wir uns, welche Eigenschaften für Konto-Instanzen in dieser Klasse festgelegt werden müssen: EinKonto besitzt auf jeden Fall eine Kontonummer, einenKontoinhaber und einen Kontostand. Wir benötigen eineMethoden zum Einzahlen, eine zum Abheben, eine zumÜberweisen. Aber auch zum Auslesen des Kontostands werdenwir eine Methode verwenden. Diese Vorüberlegungen(„Entwurf eines Modells“) sind von der Programmiersprachenoch weitgehend unabhängig.

Erstellen des Konto-Projekts in BlueJ:

Wir starten BlueJ und beginnen ein neues Projekt, dem wir denNamen Bank_1 geben (ein weiteres Bank-Projekt werden wirdann Bank_2 nennen). Beachten Sie die Hinweise zur Readme.txt–Datei sowie zu den Kommentarenvom ersten Beispiel.

Bei den Variablen (Datenfelder) lernen wir neue Datentypen kennen (bisher wurde nur intverwendet): Der Typ double lässt zu, dass Zahlen mit Dezimalkomma (bzw. Dezimalpunkt) alsWert zugewiesen werden können. Für den Kontoinhaber soll ein Name zugewiesen werden undnicht eine Zahl oder Nummer. Hier wird der Typ String verwendet. Genau genommen ist Stringgar kein Variablentyp, sondern eine Java-Klasse, damit wird auch der Großbuchstabe amWortanfang gerechtfertigt. In JAVA wird im Gegensatz zu einigen anderen Programmiersprachenzwischen Groß- und Kleinbuchstaben unterschieden. Klassennamen beginnen üblicherweise immermit einem Großbuchstaben. Variablen- und Methodennamen beginnen üblicherweise mit einemKleinbuchstaben. Zur Verbesserung der Lesbarkeit werden bei Wortzusammensetzungen oft mittenim Bezeichner Großbuchstaben verwendet (zum Beispiel getKontoStand ).

Die Datenfelder werden am Beginn der Klasse festgelegt (wie auch bei der Klasse 'Quader'). Dereinfachste Konstruktor könnte als Kontonummer und Kontostand jeweils den Wert 0 zuweisen, alsKontoinhaber "" oder "dummy". Das ist für das Erzeugen mehrerer Konto-Instanzen natürlich nichtsinnvoll – also wird man dafür sorgen, dass gleich beim Erzeugen einer Konto-Instanz nach demNamen und der Kontonummer gefragt wird. Der Kontostand kann mit 0 initialisiert werden, aberauch die Kontoeinrichtung mit einem Startguthaben könnte vorgesehen werden.

'Konto' besitzt nach diesen Überlegungen 3 Datenfelder und 5 Methoden (eine davon ist derKonstruktor), vergl. Kasten oben links. Es folgt der Quelltext für dieses Projekt (im folgendenwerden Quelltexte nicht als Screenshot dargestellt, sondern als Text mit Syntax-Hervorhebung; hierauß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)

Modell der Klasse 'Konto':

Klasse:Konto

Felder:ktoNummer (int)ktoInhaber (String)ktoStand (double)

Konstruktor:Konto(ktoNr,ktoInh)

Methoden:einzahlen()abheben()getKontoStand()überweisen(kto, betrag)

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 Kontonummer16: * @param ktoInh Parameter für Kontoinhaber17: */18: public Konto(int ktoNr, String ktoInh)19: { // Initialisieren der Datenfelder20: ktoNummer = ktoNr;21: ktoStand = 0;22: ktoInhaber = ktoInh;23: }24: 25: /**26: * Auslesen des Kontostands27: * 28: * @return Wert des Kontostands29: */30: public double getKontoStand()31: {32: return ktoStand;33: }34: 35: /**36: * Einzahlung vornehmen37: * 38: * @param betrag Betrag der Einzahlung39: */40: public void einzahlen(double betrag)41: { 42: ktoStand = ktoStand + betrag; 43: }44: 45: /**46: * Auszahlung vornehmen, falls Kontostand ausreichend47: * 48: * @param betr Betrag der Auszahlung49: */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 vornehmen60: * 61: * @param empfaenger Konto des Empfängers62: * @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 dieals Parameter übergebenen Werte in die Datenfelder der jeweiligen Instanz ein.

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 derSchreibweise ktoStand = ktoStand + betrag muss man sich klar machen, dass es sichnicht um eine Gleichung handelt, sondern um eine Wertzuweisung: Zuerst wird der Wertvon ktoStand + betrag ermittelt, dann wird dieser wieder dem Datenfeld ktoStandzugewiesen.Die Schreibweise ist professionellen Programmierern noch zu umständlich, deshalb ist auchdie kürzere – aber besonders für den Anfänger erheblich schwerer lesbare – Schreibweisezugelassen, die dasselbe bewirkt: ktoStand += betrag

4. Das Auszahlen entspricht dem Einzahlen eines negativen Betrags, deshalb kann man dieMethode zum Einzahlen verwenden. Hier im Beispiel wurde einmal angenommen, dass mandas 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ößeroder gleich. Die weiteren sind <= für kleiner oder gleich und == für gleich (s. S. 13).

5. Die interessanteste Methode ist hier die zum Überweisen. Beim Überweisen wird derangegebene Betrag vom Konto abgehoben und beim angegebenen Konto(-Objekt)eingezahlt. Das Überweisen eines negativen Betrags ist nicht verhindert, woraus sichnatürlich ein Auftrag zur Programm-Verbesserung ergibt! Die Syntax für die if-Anweisungkann der Methode auszahlen entnommen werden.

Hinweis zum Ausführen des Konstruktors: Der Kontoinhaber muss mit Anführungszeichen("Meier") eingegeben werden! Probieren Sie das Überweisen aus, nachdem mindestens zweiKonten erzeugt worden sind und auf das Absender-Konto ein (positiver) Betrag eingezahlt wurde!Als Parameter muss hier der Name des Konto-Objekts für das Empfängerkonto eingegeben werden,dies kann auch mit Mausklick auf das Objektsymbol erfolgen.

Fragen und Aufgaben zum Text8. Wie verfährt ein Konto im dargestellten Quelltext bei einer Überweisung, wenn die Deckung

nicht ausreicht? Testen Sie es, überprüfen Sie die Kontostände!9. Steht in der Methode ueberweisen die Variable empfaenger für den Inhaber des

Empfängerkontos oder für die Konto-Instanz des Empfängerkontos? Begründen Sie!

Erstellen einer vollständigen Übersicht zur Klasse 'Konto'

Wir wählen den Menüpunkt Werkzeuge- Dokumentation erzeugen. Dieser Menüpunkt erstellt einehtml-Seite (Text-Format für Web-Seiten) und zeigt sie im Standard-Browser an (es dauert vielleicht einWeilchen). Auf dieser html-Seite istalles beschrieben, was als publicdeklariert ist – die als privatedeklarierten Datenfelder erscheinennicht. Wer unsere Klasse 'Konto' ver-wenden will, muss nicht wissen, ob wirdie intern verwendete Variable für dieKontonummer kontoNummer oderktoNr genannt haben, weil er daraufnicht zuzugreifen braucht (s. auch S.15).

JAVA-Einführung, Seite 11

Wenn Programmierer Java-Klassen austauschen oder weitergeben, geben sie in der Regel auch dieDokumentation mit. Die Klassen können als Quelltext (Datei mit der Extension „.java“) oder alscompilierte Klasse (Extension „.class“) weitergegeben werden. Sie finden diese Dateien, wenn Siemit 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 dieBedeutung 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 differenziertenBeschreibung 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 einevöllig gleichartig aufgebaute Webseite geführt, welche die Klasse 'String' beschreibt. Auf diesenTyp von Webseiten trifft man (fast) immer, wenn man Erklärung zu JAVA-Klassen sucht.Kommentare, die dagegen mit // eingeleitet wurden (einzeilige Kommentare), sind als Notizenaufzufassen, die der Programmierer für sich selbst (oder einen Leser des Quelltextes) angefertigthat. Das gilt auch für die mehrzeiligen Kommentare, die zwischen '/*' und '*/' stehen.

Fragen und Aufgaben zum Text10. 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ßendfü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 Kontosauf. 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 anderesjeweils der Name des Kontos eingegeben werden muss, und dass es hier nicht über die Eingabe derKontonummer geht. Die Ursache liegt darin, dass es kein „übergeordnetes“ Objekt gibt, das dieFähigkeit besitzt, aus der Kontonummer zu ermitteln, welche Kontoinstanz dazu gehört. Wenn manbei 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_2Legen Sie ein neues Projekt mit dem Namen 'Bank_2' an. Dieses Projekt verwendet wieder eineKlasse 'Konto', dessen Quelltext fast vollständig mit dem des vorigen Projekts übereinstimmenwird. Klicken Sie nicht auf „Neue Klasse“, sondern wählen Sie im Menü „Bearbeiten / Klasse ausDatei 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 diesemProjekt mit dem Namen 'Bank' – dies wird damit unser erstesProjekt, in dem wir zwei Klassen definieren.Die Konten, die im Bankmodell verwaltet werden sollen,müssen in irgendeiner Form gespeichert werden. JAVA stelltdafür die Klasse ArrayList zur Verfügung. Instanzen dieserKlasse sind Listen-Objekte, sie besitzen Methoden zumVerwalten der Listenelemente. Die wichtigste ist die zumHinzufügen. Natürlich kann eine solche Liste eingetrageneElemente auch wieder löschen, eine „Kontoauflösung“ ist aberhier bei unserem Bankmodell nicht vorgesehen. Damit solcheListen-Objekte vielseitig sind, verwalten sie nur Zeiger auf dieeingetragenen Elemente, aber keine Information darüber, vonwelchem Typ die eingetragenen Elemente sind. Die Liste merktsich also in unserem Beispiel nicht, ob ein Konto oder ein Quadrat eingetragen ist – dieKonsequenzen 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 dieserKlasse erst eine Instanz (kontoListe) erzeugt werden, bevor sie verwendet werden kann. Dasgeschieht mit der Zeile 20 im Konstruktor für das Bankobjekt: Hier wird der Konstruktor vonArrayList aufgerufen. Diese Syntax (new ...) haben Sie vielleicht auch schon bei der Erzeugungder 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: }

Modell der Klasse 'Bank':

KlasseBank

Felder:Liste der Konten

KonstruktorBank()

MethodenneuesKonto()einzahlen()abheben()getKontoStand()ueberweisen()

JAVA-Einführung, Seite 13

Anders als im vorigen Beispiel werden neue Konten jetzt nicht mehr durch BlueJ nach Rechtsklickauf das Klassensymbol für 'Konto' erzeugt, sondern durch die Methode neuesKonto einesBankobjekts. Wir müssen also erst ein Bankobjekt erzeugen, dann können wir nach Rechtsklick aufdas Objektsymbol dessen Methode neuesKonto() aufrufen, die den Konstruktor der Klasse 'Konto'verwendet. Das neu erzeugte Konto – besser eine Referenz darauf (auch „Zeiger“ genannt) – wirddann mit add in die Liste eingetragen. Eine Bankinstanz verwaltet so jedes erzeugte Konto in seinerListe 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 Listeeingetragen 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 inacheinander die Werte 0, 1, …, 4 annimmt. Die Schleife wird auch dann 5 mal durchlaufen, wenndas 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 izurück gibt, muss dieser vor der Zuweisung an die Variable einKonto eine Typumwandlungerfahren. Das geschieht durch das vorangestellte (Konto) – der Fachmann spricht dabei von einem„Cast-Operator“. Eine unpassende Typumwandlung kann schlimme Fehler verursachen, deshalbgibt 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 JAVAsteht das Ausrufezeichen für die Negation, != heißt also „ungleich“. Die if-Anweisung ist hier ohneelse verwendet worden. Bei ungültiger Kontonummer wurde ein Hinweis bereits vonfindByNumber ausgegeben. Weil die Anweisung in Zeile 70 bzw. 83 so kurz ist, wird auf den sonstbei 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 diesein 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 absdund 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 Anweisungenstehen, sind geschweifte Klammern zur Kennzeichnung von Anfang und Ende des Blockserforderlich. 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 unserBankinstitut eröffnen und Kundenkonten einrichten, umdie von uns programmierten Klassen und derenInstanzen zu testen! Also: Bankinstanz mit Rechtsklickerstellen, Bank-Namen wählen (z.B. "JGiro", "DieBank"o.ä.) und dann in dieser Bank mindestens 2 Konteneinrichten. 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. DieseBeziehung „Bank verwendet Konto“ (allgemein„<Klasse> verwendet <AndereKlasse>“) stellt BlueJdurch einen gestrichelten Pfeil in der Projektübersichtdar.

Fragen und Aufgaben zum Text12. 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 eineAuszahlung/Ü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 Bankbenötigt die Methode findByNumber, die wir aber beim simulierten Zahlungsverkehr mit der Mausim 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öglichenMethoden beim Rechtsklick auf einBankinstanzsymbol um eine unnötigeZeile unübersichtlicher geworden, wiedie 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 einesinnvoll benannte Methode. Ein Datenfeld fahrPreis vom Typ double muss dann dengewünschten Fahrpreis speichern. Zum Testen des Automaten ist es zweckmäßig, bereits imKonstruktor den Fahrpreis mit z.B. 3.8 zu initialisieren – dann muss man nicht bei jedemNeustart 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. DieKlasse benötigt im Prinzip also eine Methode einzahlen(betrag) wie im vorigen Projekt.Ein weiteres Datenfeld einwurf vom Typ double muss den bereits gezahlten Betragspeichern.

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 derKauf abgeschlossen, und die Höhe des Wechselgeldes wird ausgegeben. Außerdem muss dereingeworfenen Betrag auf 0 zurückgesetzt werden. Info zum „Drucken“:System.out.println (print line)gibt eine Zeile, also Text mit an-schließendem Zeilenumbruch aus.Neu ist hier: System.out.print(ohne ln) gibt Text aus, ohne dass sich ein Zeilenumbruch anschließt. Sie können die beidenletzten 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 ZahlfahrPreis dazu in einen String um.

4. Diesen Punkt können Sie ergänzen, nachdem alles andere fehlerfrei läuft:

System.out.println("BlueJ-Bahngesellschaft");System.out.print("Fahrkahrte zu "); // TextSystem.out.println(fahrPreis); // Wert... (u.s.w.)

JAVA-Einführung, Seite 17

Die Klasse soll ein drittes Datenfeld gesamtEinnahmen besitzen, in dem die Einnahmen beijedem 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 zumAbbrechen des Fahrkartenkaufs ergänzen. Sie sollte als Text die Rückzahlung des bishereingeworfenen Betrags melden. Was muss sie sonst noch tun?

Die Abbildung zeigt einmögliches Ergebnis desProjekts: Sie können denNamen des Projekts, denNamen der Klasse und denaktuell gewählten Namenfür die Instanz dieser Klasseherauslesen.Ein Fahrpreis wurde fest-gelegt, Geld wurde „einge-worfen“. Das Bild zeigt das Fensternach Aufruf der MethodedruckeFahrkarte.

Mit Sicherheit wird Ihr Ergebnis noch nicht sowie hier aussehen können, denn hier wurde dieAusgabe auf 2 Nachkommastellen und mitDezimalkomma formatiert. Diese Formatierung rundet zugleich, so dass Rechenfehler ausgeglichenwerden. Es folgen hierzu weitere Informationen:

Wie entstehen Rechenfehler beim Computer?Computer rechnen im Zweiersystem. Brüche wie

12 ,

14 ,

18 ,

58 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 ausPotenzen von 2 oder 5 zusammensetzt, wird der Dezimalbruch periodisch. 2 und 5 sind Teiler der

Basis 10, daher ist z.B. 3

25= 3

52=12100

=0,12 abbrechend. 4

11=0,36 ist dagegen periodisch. Da die

Basis 2 nur die 2 als echten Teiler hat, können im Zweiersystem nur Brüche wie die oben genanntenabbrechend sein,

15 oder

110 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 sichbeim Fahrkartenautomaten z.B. bei einem Fahrschein zu 3,80€, wenn 0,10€ bezahlt sind. AlsRestbetrag werden 3,699999999999997€ berechnet! (Probieren Sie es aus!)

Zahlen formatierenJAVA stellt verschiedene Methoden zum Formatieren von Zahlen zur Verfügung. In JAVA sind alleMethoden 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 Beginnden Text „Noch zu zahlen: “. Das %-Zeichen kennzeichnet das Einfügen aus nachfolgendangegebenen Parametern. „.2“ kennzeichnet die Genauigkeit von 2 Nachkommastellen, „f“kennzeichnet die Umwandlung eines float- oder double-Werts (Fließkommazahl). Die weiterenZeichen „ €“ 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 desBetriebssystems.Die format-Methode der Klasse String ist sehr vielseitig, mit ihr können z.B. auch Datumswerteformatiert werden (siehe nachfolgendes Kapitel). Ein weiteres Beispiel für die Formatierung auf 2Nachkommastellen:

System.out.println(String.format("Fahrkahrte zu %.2f €",fahrpreis));

Diese Art der Formatierung können Sie überall dort verwenden, wo ein Euro-Wert mit 2Nachkommastellen ausgeben werden soll.

5. Fünftes Projekt: Person (Vererbung / GregorianCalendar)Ein bedeutendes Merkmal objektorientierter Programmierung (und darum geht es bei JAVA) ist dieMöglichkeit, bereits programmierte Klassen als Ausgangsbasis für weitere Klassen mit zusätzlichenDatenfeldern und Methoden zu verwenden. Die so von einer Basisklasse „abgeleiteten“ Klassenerben die Datenfelder und Methoden der Basisklasse, wodurch der Quelltext der neuen Klasseweniger umfangreich ist. Die Verwendung fertiger Basisklassen ist für den Programmierer einedeutliche 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 eineKlasse mit der Bezeichnung Person. Eine Person hat einen Vornamen, einen Nachnamen, einGeburtsdatum. Außerdem sollvermerkt werden können, obdie Person Informatiker ist odernicht. Vor- und Nachname sindStrings, das Geburtsdatummüssen wir als Instanz der inJAVA vordefinierte KlasseGregorianCalendar festlegen(die Bezeichnung bezieht sichauf den GregorianischenKalender, der seit dem 15.Oktober 1582 regelt, welcheJahre Schaltjahre sind). DieInformatiker-Eigenschaft kannnur die Werte true oder falseannehmen, dieser Typ heißtboolean. Wenn eine Persongeboren wird, steht dasGeburtsdatum fest – darumwird hier vorgeschlagen, dassder Konstruktor beim Erzeugeneiner Instanz der Klasse PersonTag, Monat und Jahr der Geburterfragt.

JAVA-Einführung, Seite 19

Wenn wir jetzt eine Instanz erzeugen, müssen wir also Werte für t, m, j eingeben. DaGregorianCalendar die Monate als Zahlen von 0 bis 11 verwaltet, muss die Eingabe für m um 1vermindert werden!

Beim Inspizieren der Person werden Siefeststellen, dass Sie das Geburtsdatumnicht in der Form von Tag, Monat undJahr auslesen können. Möchten Sie eineMethode getGeburtsdatum() schrei-ben, die dieses Datum als String zu-rückgibt? Dazu müssen Sie heraus-finden, wie aus der InstanzgeburtsDatum ein Datumsstring gewon-nen werden kann! Sie müssen jetzt keineSuchmaschine 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 derBeschreibung der Klasse Stringetwas weiter unten die Beschrei-bung der beiden format-Metho-den.

Klicken Sie wie in der Abbildungangedeutet auf „format“, von dortkönnen Sie zu einer so umfang-reichen Beschreibung gelangen,wie ein „format string“ aussehenkann, dass Sie erleichtert seindürften, einen Weg zur formatier-ten Ausgabe eines Datums auchim 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 zuformatieren, dass zusätzlich noch der Wochentag ausgegeben wird (Aufgabe 22)!

Anmerkungen: Methoden, die Daten auslesen, beginnen üblicherweise mit get. Daran lehnt sichhier der Vorschlag für den Methodennamen zum Auslesen des Geburtsdatums an. Wenn Sie solcheSprachvermischungen vermeiden wollen, können Sie getDayOfBirth oder holeGeburtsdatumverwenden. Ein Vorteil deutscher Wortanteile ist der, dass sofort erkennbar ist, ob vordefinierte odereigene Bezeichner verwendet sind.Zur Übung – und damit unsere „Person“ etwas mehr zu vererben hat (darum geht es ja in diesemKapitel), folgen zunächst noch einige Aufgaben:

Fragen und Aufgaben zum Text15. 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 Wertsetzt, den der Anwender eingibt.

20. Schreiben Sie eine Methode getGanzerName(), die die Kombination aus Vor- und Nachnamenals String zurück gibt.

21. Schreiben Sie eine Methode druckeGanzenNamen(), die mit System.out.println denvollständigen Namen auf das Konsolenfenster ausgibt. Diese Methode sollte getGanzerNameverwenden!

22. Schaffen Sie es, das Geburtsdatum einschließlich Wochentag auszugeben?

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

JAVA-Einführung, Seite 21

VererbungJetzt 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 diemeisten Lehrer am Gymnasium zutrifft).

Natürlich könnte man den Quelltext von Person kopieren, um alles zu übernehmen, und manmüsste nur die Klassenbezeichnung (Objektklasse, nicht Schulklasse – der Begriff „Klasse“ ist indiesem Abschnitt leider nicht eindeutig!) im Konstruktor anpassen. Für den Zugriff aufUnterrichtsfächer bzw. die Schulklasse wären noch wenige Methoden zu ergänzen. Dann hätten wiraber einen großen Teil des Quelltextes 3 mal zu verwalten. Ein Fehler in der Berechnung des Altersmüsste in 3 Textdateien korrigiert werden. Um solche Nachteile zu vermeiden, wurde dieMöglichkeit geschaffen, von vorhandenen Klassen erweiterte Klassen abzuleiten. Die abgeleitetenKlassen erben dann alle Eigenschaften und Methoden der Vorgängerklasse. Zunächst erstellen wir in unserem Projekt eine neueKlasse mit der Bezeichnung „Schüler“ (oder „Schueler“)und eine weitere mit der Bezeichnung „Lehrer“.

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

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

Methode 2: Wir fügen in derKlasse Schüler die zweiWörter extends Person ein(s. Abb.).

public class Schüler extends Person

{

.... <u.s.w.> ...

}

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;}

JAVA-Einführung, Seite 22

Die Konstruktoren der neuen Klassensollen nun so überarbeitet werden, dass sieLehrer- bzw. Schülerinstanzen mit Ge-burtsdatum erzeugen:Ein Konstruktor der abgeleiteten Klassemuss einen Konstruktor der Vorgänger-klasse durch Verwendung des Schlüssel-worts super aufrufen. Für die KlasseLehrer sind hier als Beispiel zwei Kon-struktoren angegeben.Ganz ähnlich gestalten wir den Quelltextfür die Klasse Schüler.

Wenn Sie jetzt Instanzen von Lehrer undSchüler erzeugen, stehen diesen alleMethoden von Person zur Verfügung.

Fragen und Aufgaben zum Text:23. Ergänzen Sie für die Klasse Schüler

eine Methode zum Setzen der Schul-klasse!

24. Erzeugen Sie Instanzen von Person,Schüler, Lehrer und testen Sie deren

Methoden, so dass z.B.beim Inspizieren vonschüler1 die abgebildeteSituation entsteht!

ÜberschreibenWenn eine Klasse eineVorgängerklasse erweitert,so erbt sie deren Metho-den. Manchmal ist essinnvoll, eine geerbte Me-thode für die erweiterteKlasse speziell anzu-passen. Man könnte zumBeispiel annehmen, dassein Lehrer auch das FachInformatik unterrichtet,wenn er Informatiker ist.

/** * Beschreibung der Klasse Schüler. * * @author B.Spier * @version Jan. 2014 */public class Schüler extends Person{ String klasse;

/** * Konstruktor für Schüler */ public Schüler(int t, int m, int j) { super(t, m, j); klasse = ""; }}

/** * Beschreibung der Klasse Lehrer. * * @author B. Spier * @version Jan. 2010 */public class Lehrer extends Person { private String fach1, fach2; /** * Konstruktoren für Lehrer */ public Lehrer(int t, int m, int j) { super(t, m, j); } public Lehrer(int t, int m, int j, String f1, String f2) { super(t, m, j); fach1 = f1; fach2 = f2; }}

JAVA-Einführung, Seite 23

Es soll jetzt die Methode setInfomatikerYes()speziell für Lehrer erweitert werden, so dass dabeifach2 auf „Informatik“ gesetzt wird.

Weil informatiker in Person als private deklariertist, verwenden wir die geerbte öffentliche MethodesetInformatikerYes() von Person. Nun kann aber public void setInformatikerYes() { setInformatikerYes(); fach2 = "Informatik"; }

nicht funktionieren, weil jetzt die Methodedes Lehrers immer wieder sich selbst aufruft,anstatt auf die geerbte Methode zuzugreifen!Die Lösung ist das Schlüsselwort super, daswir schon beim Aufruf des geerbtenKonstruktors kennen gelernt haben (s. rechts).

Als Nachweis, das dies wirklich funktioniert, ergänzen wir einige Zeilen in der Klasse Schüler:public class Schüler extends Person{ String klasse; Person einLehrer; // <--- ERGÄNZUNG

public Schüler(int ta, int mo, int ja) { super(ta, mo, ja); klasse = ""; einLehrer = new Lehrer(2,5,1961); // <--- ERGÄNZUNG einLehrer.setInformatikerYes(); // <--- ERGÄNZUNG }//...}

Erzeugen Sie jetzt eine Instanz von „Schüler“. Inspizieren Sie diesen Schüler, inspizieren Sie danndessen Objekt einLehrer!

Dass einLehrer einem Datenfeld vom Typ Person zugewiesen wurde, hat hier keine Auswirkung,es hätte ebenso gut auch ein Feld vom Typ Lehrer verwendet werden können.

Methode in der Basisklasse „Person“(Lösung von Aufgabe 18):

public void setInformatikerYes() { informatiker = true; }

Methode, die in der Klasse „Lehrer“ ergänztwird, und damit die geerbte überschreibt: public void setInformatikerYes() { super.setInformatikerYes(); fach2 = "Informatik" }

JAVA-Einführung, Seite 24

6. Sechstes Projekt: Wir programmieren ein Applet

Das Wort Applet ist eine zusammengesetztes Kunstwort, das aus Application (= Anwendung) undSnippet (= Schnipsel) gebildet ist. Es bezeichnet hier ein JAVA-Programm, das in einem Web-Browser läuft. Mit der Bearbeitung dieses Kapitels schreiben Sie also ein Programm, dassunabhängig von BlueJ läuft. Sie können es weitergeben oder auf Ihre Homepage setzen. Es kann aufjedem Computer laufen, auf dem eine JAVA-runtime-engine installiert ist, also auch unter anderenBetriebssystemen als Windows. Auch wenn unser erstes Beispiel nichts Beeindruckendes leistet, sozeigt es doch im Ansatz die Möglichkeiten, die sich mit Applets eröffnen!

Wir beginnen ein neues Projekt und legen dafürden Namen Zeichnen_1 fest, denn wir werdenauf der Applet-Fläche ein wenig zeichnen.(Kreise? Quadrate? Linien? Ausgefüllte Flä-chen? Man wird sehen!)Für die neue zu erstellende Klasse wählen wirden Namen Applet1. Wichtig: Art der Klasse istjetzt nicht die Voreinstellung „Klasse“, sondern„Applet“!

Das schon recht umfangreiche Quelltext-Gerüst,das BlueJ vorgibt, reduzieren wir in diesemProjekt zunächst auf die folgenden wenigenZeilen:import java.awt.*;import javax.swing.*;

/** * Minimal-Applet * * @author B.Spier * @version Feb.2010 */public class Applet1 extends JApplet{ /** * Methode, die für das gewünschte Aussehen der Appletfläche sorgt. * (public: wird von dem Programm aufgerufen, welches das Applet darstellt) * @param g das Graphics-Objekt für dieses Applet */ public void paint(Graphics g) { // einfacher Text wird im Applet angezeigt. Er beginnt bei x=20 // und y=30, bezogen auf die obere linke Ecke der Appletfläche. g.drawString("Dies ist ein JApplet!", 20, 30); }}

Jetzt erkennen Sie deutlich: Die Klasse Applet1 ist von JApplet abgeleitet. Sie hat eine Fülle von Methoden von JApplet und dessen Vorgängerklassen geerbt (bei Interesse sehen Sie sich die Dokumentation an!).Außerdem sollte Ihnen auffallen: Es gibt hier keine Methode public Applet1() { } – diese Klasse hat also keinen eigenen Konstruktor! Zwar können Sie mit BlueJ eine new-Methode aufrufen, das ist dann ein von einem Vorgänger geerbter Konstruktor ohne Parameterübergabe. Den Konstruktor brauchen wir aber nicht, denn zum Ausführen von Applets rufen wir nie einen Konstruktor auf! Das übernimmt die installierte JAVA-Umgebung, wenn ein Applet „zum Laufen gebracht“ wird. Dazu führen Sie folgende Schritte aus:

JAVA-Einführung, Seite 25

Klicken Sie mit der rechten Maustaste auf das Applet1-Symbolund wählen Sie den Punkt „Applet ausführen“. Bevor nun dasApplet ausgeführt wird, können Sie zwischen zwei Varianten derAusführung wählen: Browser oder Appletviewer. Der Applet-viewer ist deutlich schneller, weil er nicht eine kompletteBrowser-Oberfläche laden muss. Nehmen Sie also diesen für denersten Test dieses Applets. Außerdem können Sie die Breite undHöhe der Applet-Fläche einstellen, die Abbildung zeigt dasApplet bei 200×80 Pixeln.Ob Sie das Applet im Viewer anzeigen, im Browser anzeigen, oder nur die Webseite erstellen: Injedem Fall wird eine html-Textdatei erzeugt, die mit jedem Browser dargestellt werden kann. Siefinden sie in Ihrem Projektordner und können Sie von dort (auch ohne BlueJ) mit dem Internet-Explorer (Firefox, GoogleChrome usw.) öffnen.

Wählen Sie erneut „Applet ausführen“, wählen Sie jetzt aber „Applet im Browser ausführen“.Die Abbildung links stellt das Applet im Internet-Explorerdar. Je nach Sicherheitseinstellungen müssen Sie eventuell dieAusführung von JAVA-Applets zulassen, bevor das Appletangezeigt wird.

Die html-Seite, die BlueJ für diese Darstellung erzeugt hat,befindet sich im Projektordner und heißt Applet1.html. Unter Umständen zeigen (vor allem ältere) Browser dieHintergrundfläche nicht in weiß, sondern in schwarz.

Darum soll als nächstes die Paint-Methode derart erweitertwerden, dass vor der Textausgabe der Hintergrund gelöschtwird. Außerdem zeichnen ein wir ein Rechteck, eine Linie,eine Rechteckfläche und eine Kreisfläche:

public void paint(Graphics g) { Rectangle r = getBounds(); // Applet-Position und -Größe holen g.clearRect(r.x, r.y, r.width, r.height); // Hintergrund löschen g.setColor(new Color(180,200,230)); // Farbe (RGB) setzen g.fillRect(10,10,100,50); // Rechteckfläche zeichnen g.setColor(Color.black); // vordefinierte Farbkonstante g.drawString("kleine Applet-Demo", 20, 20); g.setColor(Color.red); // vordefinierte Farbkonstante g.fillOval(70,30,60,60); // ausgefüllter Kreis g.drawRect(15,40,20,30); // Rechteck-Rand g.setColor(Color.blue); // vordefinierte Farbkonstante g.drawLine(40,30,119,119); // Linie (Start-Pos. - End-Pos.) }

Das abgebildete Applet ist in der Größe 200×120 erzeugt, Siekönnen aber die Größe des Appletviewer-Fensters noch nach-träglich verändern.

Aufbau eines HTML-QuelltextesJetzt wollen wir uns noch ein wenig mit der html-Seite befassen,die BlueJ beim „Ausführen im Browser“ erzeugt. Öffnen Siedazu die Datei Applet1.html mit dem Windows-Editor.

HTML ist die Abkürzung für hypertext markup language, eineTextform, die Markierungen und Links ermöglicht. Eine html-

JAVA-Einführung, Seite 26

Seite wird stets mit dem „Tag“ <html> eingeleitet und mit </html> beendet. Zwischen diesenTags gibt es einen head-Abschnitt, der mit <head> eingeleitet und mit </head> abgeschlossenwird, sowie einen body-Abschnitt, für den Entsprechendes gilt (<body> </body>).

Textabschnitte, die mit „<!--“ beginnen und mit „-->“ enden, sind Kommentare. Sie beeinflussendaher das Aussehen der html-Seite in keiner Weise und können gelöscht werden, nachdem Sie siegelesen haben.

Im head-Abschnitt stehen Informationen für den Browser; zwischen <title> und </title> stehtder Titel für die Kopfleiste des Browserfensters (bzw. die Registerkarte). Ändern Sie den Titel auf„Applet1 anzeigen“.Der body-Abschnittt enthält den Inhalt der html-Seite. <h1> steht für eine Überschrift (headline)mit vordefinierten Schriftattributen, ändern Sie den Text auf „Demo-Applet“. <hr> liefert einehorizontale Trennlinie, wir finden dieses Tag auch unmittelbar vor Ende des body-Abschnitts.Zwischen diesen beiden Linien steht der für die Ausführung des Applets entscheidende Code,eingeleitet mit <applet> und abgeschlossen mit </applet>. Das <applet>-Tag ist erweitertdurch Angabe der class-Datei, zu der unser Applet-Quelltext compiliert wurde, es folgen Breite undHöhe des Applet-Bereichs in der html-Seite. codebase="." wird hier nicht erläutert.

Die Zeile archive="file:/C:/Programme/BlueJ/lib/bluejcore.jar,..."verweist auf Speicherorte auf dem gerade verwendeten Computer. Löschen Sie diese Zeile! Sieführt sonst leicht zu Fehlermeldungen, wenn das Applet auf einem anderen PC laufen soll!Mit alt wird ein alternativer Text angegeben, der angezeigt wird, wenn die Anzeige des Appletsnicht funktioniert. Das daran anschließende >-Zeichen schließt das <applet>-Tag ab.

Wenn Sie noch eigenen Text in der html-Seite ergänzen möchten, können Sie das gern tun – das hiergezeigte Beispiel („Sieht das nicht schön aus?“) soll aber verdeutlichen, dass hier nur ein minimalerAspekt zum html-Aufbau dargestellt wurde. Selbst einfache Umlaute müssen als Sonderzeichenspeziell codiert werden, weshalb html-Seiten meistens mit Hilfsprogrammen geschrieben werden.Der folgende html-Quelltext liefert das abgebildete Applet-Aussehen.<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<title>Applet1 anzeigen</title>

</head>

<body>

<h1>Demo-Applet</h1>

<hr>

<applet code="Applet1.class"

width=200

height=120

codebase="."

alt="Applet wird (noch) nicht ausgeführt."

>

Ihr Browser ignoriert das &lt;APPLET&gt;-Tag!

</applet>

<hr>

Sieht das nicht sch&ouml;n aus?

</body>

</html>

(Vergleichen Sie auch mit dem html-Text, der im Anhang angegeben ist!)

JAVA-Einführung, Seite 27

Speichern Sie den Text nach den vorgenommenen Änderungen. Beachten Sie, dass bei erneutemAufruf zum „Ausführen im Browser“ BlueJ die html-Seite neu erstellt und Ihre Änderungenverloren gehen! Kopieren deshalb Sie diese Datei zusammen mit der Datei Applet1.class auf einenUSB-Stick (in einen gemeinsamen Ordner) und testen Sie dieses Applet auf einem Computer, derBlueJ nicht kennt! Vielleicht haben Sie ja sogar die Möglichkeit, dieses Applet unter Linux odereinem Apple-Betriebssystem zu testen.

7. Siebentes Projekt: Das Applet reagiert auf eine Maus-AktionIn diesem Kapitel lernen Sie, wie ein Applet auf die Betätigung einer Maustaste reagieren kann. Dasist der erste Schritt in Richtung auf ein „richtiges Programm“, also ein Applet, das auf Aktionen desAnwenders reagiert. Unsere Maus-Demo erstellen wir in 3 Versionen, die schrittweise kompakterwerden. MausDemo3 hat denkürzesten Quelltext, dieser ist aberohne MausDemo1 undMausDemo2 kaum zu verstehen.Alle 3 Maus-Demo-Applets leistendasselbe: Sie stellen auf der Applet-Fläche eine farbige Kreisfläche dar,die beim Klicken mit der Maus(genau genommen: beim Drückeneiner Maustaste) die Farbezwischen rot und blau wechselt.Dabei spielt es noch keine Rolle,ob die Kreisfläche oder der Bereichdaneben getroffen wurde.Für die Übersicht Ihrer Ordner-Struktur ist es zweckmäßig, diese 3Projekte in einem eigenen OrdnerMausdemo123 zu speichern.Wählen Sie also „Neues Projekt“,navigieren Sie zum Ordner IhrerBlueJ-Projekte, erstellen Sie einenneuen Ordner Mausdemo123,speichern Sie in diesem das neueProjekt als Mausdemo1.

Erstellen Sie zuerst die KlasseKreis. Der Konstruktor zeigt, wieman auf die Instanzvariable xzugreift, wenn der übergebeneParameter ebenfalls x heißt: thisist ein Zeiger auf die aktuelleInstanz der Klasse Kreis.

Als nächstes erstellen Sie dieKlasse MausDemo1, als „Art derKlasse“ wählen Sie „Applet“. Dienicht verwendeten vorgegebenenMethoden sind auf der folgendenSeite nicht abgebildet.

import java.awt.*;

/** Klasse Kreis: * Eine Fläche mit Farbe * * @author Spier * @version Feb.2010 */public class Kreis{ private int r; private int x, y; private Color farbe; /** Konstruktor für Kreis * @param x,y,r: Mitte, Radius */ public Kreis(int x, int y, int r) { this.x = x; this.y = y; this.r = r; farbe = Color.red; }

/** Diese Methode zeichnet die Kreisfläche. * @param grafikObjekt: Objekt, mit dem auf * die Appletfläche gezeichnet wird. */ public void zeichnen(Graphics grafikObjekt) { grafikObjekt.setColor(farbe); grafikObjekt.fillOval(x-r, y-r, 2*r, 2*r); } /** Diese Methode wechselt die Farbe * rot <--> blau und zeichnet neu. */ public void farbWechsel(Graphics gr) { if (farbe == Color.red) farbe = Color.blue; else farbe = Color.red; zeichnen(gr); // mit neuer Farbe zeichnen }}

Quelltext für die Klasse Kreis

Quelltext für die Klasse Kreis

JAVA-Einführung, Seite 28

Wenn sich beide Klassen fehler-frei übersetzen lassen, können Siedas Applet testen: Es muss einerote Kreisfläche auf weißemGrund zeigen.

Jetzt erzeugen wir im selben Pro-jekt eine weitere neue Klasse, wirnennen sie MeinMausAdapter.Diese Klasse ist eine Erweiterungder in java.awt.event.* vorde-finierten Klasse MouseAdapter.

MeinMausAdapter hat die Me-thode mousePressed geerbt. Dadiese bisher nichts tut, wird siehier so überschrieben, dass sieden Kreis mit gewechselter Farbeneu zeichnet (siehe Fortsetzungdes Quelltextes auf der nächstenSeite).

import java.awt.event.*;

/** MeinMausAdapter überschreibt die geerbte Methode mousePressed. * @author Spier @version Feb.2010 */public class MeinMausAdapter extends MouseAdapter{ /** Die geerbte Methode mousePressed von MouseAdapter tut nichts. * Hier wird sie überschrieben, so dass beim Drücken einer Maustaste * etwas geschehen kann: Kreisfarbe wechseln! * * @param e MouseEvent-Instanz, die von JAVA verwaltet wird. */ public void mousePressed(MouseEvent e) { // Wir brauchen einen Zeiger auf das Applet. MausDemo1 md1; // Der MouseEvent e besitzt die Methode getComponent(), // mit der wir diesen Zeiger erhalten.

import java.awt.*;import javax.swing.*;

/** Das Applet Klasse MausDemo1 demonstriert * die Verwendung von MeinMausAdapter, einer * Erweiterung von MouseAdapter. * (Siehe separate Quelltextdatei) * * @author Spier * @version Feb.2010 */public class MausDemo1 extends JApplet{ // das Applet verwaltet einen Kreis // MeinMausAdapter greift darauf zu, // daher nicht private! public Kreis meinKreis;

/** Wird vom Browser oder Applet-Viewer * aufgerufen, ... */ public void init() { // Workaround für ... JRootPane rootPane = this.getRootPane(); rootPane.putClientProperty(

"defeatSystemEventQueueCheck",true); // Kreis erzeugen: Mitte (40|40), Radius 35 meinKreis = new Kreis(40, 40, 35); // HIER WIRD NOCH DER MAUSADAPTER ERGÄNZT! }

// Methode zum Zeichnen des Applets public void paint(Graphics g) { Rectangle r = getBounds(); g.clearRect(r.x, r.y, r.width, r.height); meinKreis.zeichnen(g); }}

Quelltext für MeinMausAdapter (Teil 1)

Quelltext für MeinMausAdapter (Teil 1)

Quelltext für das Applet MausDemo1 (vorläufig)

Quelltext für das Applet MausDemo1 (vorläufig)

JAVA-Einführung, Seite 29

In der Methode mousePressed muss auf das Applet zugegriffen werden, um auf dessen Kreiszugreifen zu können. Da die Kreis-Methode "farbWechsel" als Parameter das Graphics-Objektdes Applets benötigt, müssen wir ihr dieses übermitteln. Das Applet hat freundlicherweise dieMethode getGraphics() geerbt, mit der wir dieses Graphics-Objekt erhalten.

Wenn sich diese Klasse fehlerfrei übersetzen lässt, können Sie fortfahren: Der Mausadapter mussnun in das Applet „eingebaut“ werden. Das geschieht in der init-Methode von MausDemo1, direktnach dem Erzeugen des Kreises (siehe Seite 28), durch Einfügen derabgebildeten Zeilen.

Zunächst wird hier also eine Variable vom Typ MeinMausAdapter deklariert, sie wird noch inderselben Zeile initialisiert. Der Konstruktor-Aufruf (ohne Parameter) führt auf einen geerbtenKonstruktor. Dann wird diese Instanz unseres Mausadapters durch die (geerbte) MethodeaddMouseListener in das Applet eingebunden. Wenn Sie es gern kürzer wünschen, geht es auch ineiner einzigen Zeile ohne Verwendung einer Variablen: addMouseListener(new MeinMausAdapter());

Auch wenn die Zusammenhänge kompliziert erscheinen: Nur Dank der geerbten Methoden bleibtder Umfang des Quelltextes bei diesem Projekt überschaubar!

Wenn Sie jetzt das Applet MausDemo1 ausführen, sollte der Kreis bei Maustasten-Betätigung dieFarbe wechseln – sonst müssen Sie sich auf Fehlersuche begeben!

Kommen wir jetzt zu Mausdemo2.Öffnen Sie Mausdemo1, falls es nicht das aktuelle Projekt ist. Wählen Sie jetzt im BlueJ-Hauptfenster den Menüpunkt „Speichern unter...“ und speichern Sie das vorhandene Projekt alsMausdemo2. Löschen Sie jetzt in diesem Projekt die Klasse MeinMausAdapter! Bearbeiten Sie dannden Quelltext von MausDemo1 (noch fand keine Umbenennung der Appletklasse statt) wienachfolgend beschrieben. Vorhandene Kommentare passen Sie so weit an, wie erforderlich – siesind hier nicht mit aufgeführt. Im Übrigen besteht die Änderung hauptsächlich darin, dass dieKlasse MeinMausAdapter jetzt innerhalb der Klasse MausDemo1 deklariert wird. Das ist einerseitssinnvoll, weil sie speziell nur für dieses Applet entworfen ist. Andererseits braucht sie jetzt keinenZeiger mehr auf das Applet aus dem MouseEvent zu ermitteln, weil sie als Bestandteil des Appletsauf dessen gesamte Methoden und Datenfelder problemlos zugreifen kann.

Und nun geht es los: Vergessen Sie nicht, die zusätzliche import-Anweisung (java.awt.event.*) zu ergänzen!

Das Umbenennen der Klasse in MausDemo2 erfolgt im Quelltext (hinter dem Schlüsselwort class).Die Umbenennung kann sich aber erst auswirken, wenn sich der Quelltext fehlerfrei kompilierenlässt, also erst nach der vollständigen Anpassung dieses Quelltextes, so wie er auf der folgendeSeite dargestellt ist.

// Vor der Zuweisung ist eine Typumwandlung nötig: md1 = (MausDemo1) e.getComponent(); // Graphics-Objekt holen und damit den Farbwechsel ausführen: md1.meinKreis.farbWechsel(md1.getGraphics()); }} Quelltext für

MeinMausAdapter (Teil 2)

Quelltext für MeinMausAdapter (Teil 2)

MeinMausAdapter mausReaktion = new MeinMausAdapter();addMouseListener(mausReaktion);

Diese Ergänzung vervoll­ständigt den Quelltext für das Applet MausDemo1.

Diese Ergänzung vervoll­ständigt den Quelltext für das Applet MausDemo1.

JAVA-Einführung, Seite 30

Wenn Sie diesen Applet-Quelltextfehlerfrei übersetzen konnten,prüfen Sie, ob Sie die Klasse schonvon MausDemo1 in MausDemo2umbenannt haben, holen Sie esgegebenenfalls nach und übersetzenSie erneut.Beachten Sie, dass hier dasDatenfeld meinKreis als privatedeklariert werden kann!

Auch meinMausAdapter ist nichtöffentlich, denn nur MausDemo2braucht darauf zuzugreifen.Die Vorteile überwiegen deutlich,üblicherweise werden deshalb Reak-tionen auf Aktionen mit der Mausdaher so wie hier oder so wie nach-folgend in Mausdemo3 program-miert!

Speichern Sie nun das Projekt alsMausdemo3 und passen Sie denQuelltext wie abgebildet an:

Mausdemo3 unterscheidetsich von Mausdemo2 darin,dass die ErweiterungMeinMausAdapter vonMouseAdapter nicht mehrexplizit aufgeführt wird. DieErweiterung ist vielmehranonym direkt in den Aufrufdes Konstruktors integriert,indem sie sich diesemunmittelbar anschließt, undzwar eingeschlossen in ge-schweiften Klammern. Erstdann folgt die schließenderunde Klammer vonaddMouseListener().

import java.awt.*;import javax.swing.*;import java.awt.event.*;

public class MausDemo3 extends JApplet{ private Kreis meinKreis; public void init() { JRootPane rootPane = this.getRootPane(); rootPane.putClientProperty( "defeatSystemEventQueueCheck", true);

meinKreis = new Kreis(40, 40, 35);

addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { meinKreis.farbWechsel(getGraphics()); } }); }

public void paint(Graphics g) { Rectangle r = getBounds(); g.clearRect(r.x, r.y, r.width, r.height); meinKreis.zeichnen(g); }}

import java.awt.*;import javax.swing.*;import java.awt.event.*;

public class MausDemo2 extends JApplet{ private Kreis meinKreis;

public void init() { JRootPane rootPane = this.getRootPane(); rootPane.putClientProperty( "defeatSystemEventQueueCheck", true);

meinKreis = new Kreis(40, 40, 35);

addMouseListener(new MeinMausAdapter()); }

public void paint(Graphics g) { Rectangle r = getBounds(); g.clearRect(r.x, r.y, r.width, r.height); meinKreis.zeichnen(g); }

private class MeinMausAdapter extends MouseAdapter

{ public void mousePressed(MouseEvent e) { meinKreis.farbWechsel(getGraphics()); } }}

Quelltext für das Applet MausDemo2 (Kommentare nicht dargestellt)

Quelltext für das Applet MausDemo2 (Kommentare nicht dargestellt)

Quelltext für das Applet MausDemo3 (Kommentare nicht dargestellt)

Quelltext für das Applet MausDemo3 (Kommentare nicht dargestellt)

JAVA-Einführung, Seite 31

Sinnvolle Verbesserungen der Mausdemo:

In Hinblick auf ein Puzzle-Spiel, das wir im nächsten Kapitel programmieren, wollen wirMausdemo2 (oder Mausdemo3) in zwei Schritten noch verbessern:

– Die Farbe des Kreises soll sich nur ändern, wenn er beim Anklicken getroffen wurde.– Nur mit der linken Maustaste soll die Farbe gewechselt werden können, weil üblicherweise

nur diese Taste Aktionen auslöst.

Für den ersten Schritt ergänzen wir in der Klasse Kreis eine Methode istdrin(), die true zurückgibt, wenn die übergebenen Koordinaten einen Punkt innerhalb der Kreisfläche beschreiben, undsonst false. Die Rückgabe ist also vom Typ boolean, die ganze Methode lautet: /** * Diese Methode prüft, ob der durch (u|v) beschriebene Punkt * im Innern des Kreises liegt. * @return true, falls Punkt im Innern */ public boolean istdrin(int u, int v) { // Anwendung des Satzes von Pythagoras: return ((u-x)*(u-x) + (v-y)*(v-y) <= r*r); }

Jetzt erweitern wir die Methode mousePressed so, dass sie prüft, ob der Kreis getroffen wurde: public void mousePressed(MouseEvent e) { int mausX = e.getX(); int mausY = e.getY();

if (meinKreis.istdrin(mausX, mausY)) { meinKreis.farbWechsel(getGraphics()); } }

Zur Erläuterung: Der Mausklick wird von JAVA registriert. Dabei werden Mausposition undbetätigte Taste erkannt. Weil unser Applet einen MouseListener einbaut, gibt JAVA diese Daten anunser Applet (genauer an den MouseAdapter) weiter. Der MouseAdapter ruft dann je nach Aktioneine seiner Methoden (mousePressed, mouseClicked, mouseReleased o.ä.) auf. Die Mausdatenwerden dabei mit einer Instanz der Klasse MouseEvent übermittelt. Diese Instanz heißt hier e (für„event“), ihre Methoden getX und getY liefern die Mausposition.

(Die Methode mouseClicked ist hier leider weniger geeignet, denn sie wertet eine Mausaktion nur dann alsKlick, wenn das Loslassen der Maustaste an genau derselben Position wie das vorherige Drücken derMaustaste geschieht. Man muss also mit ruhiger Hand klicken! Im Interesse besserer Lesbarkeit ist dasDrücken der Maustaste in diesem Kapitel manchmal als Klicken bezeichnet.)

Um jetzt nur auf die linke Maustaste zu reagieren, testen wir zusätzlich den Wert, dene.getButton() liefert – dazu muss nur die if-Zeile von mousePressed erweitert werden: if (meinKreis.istdrin(mausX, mausY) && e.getButton() == MouseEvent.BUTTON1)

Zwei Anmerkungen: BUTTON1 ist eine Konstante, die in der Klasse MouseEvent definiert ist. DieVerknüpfung && ist ein logisches UND, sie unterscheidet sich vom einfachen & dadurch, dass diezweite Bedingung nicht mehr geprüft wird, wenn die erste Bedingung bereits false ist. Das bringtim Prinzip einen Geschwindigkeitsvorteil!

JAVA-Einführung, Seite 32

8. Achtes Projekt: Das Puzzle mit 25 FeldernIn diesem Kapitel programmieren wir ein richtiges Spiel, dasvielleicht nicht nur Ihnen Freude macht, sondern auch Bekanntenaus Ihrem Umfeld. Sie können es also weitergeben an Mit-menschen, die gerne Denksport betreiben oder sich für sehrschlau halten! In dem Spiel geht es darum, alle zunächst weißenKreise durch Anklicken rot zu färben. Das Problem besteht darin,dass die Nachbarfelder bei jedem Klick ebenfalls die Farbewechseln!

Beginnen Sie ein neues Projekt und geben Sie ihm den Namen25er-Puzzle. Da unser Puzzle die Klasse Kreis aus denMausdemo-Projekten verwendet, wählen Sie jetzt im Menü vonBlueJ den Punkt „Projekt/Importieren...“ und importieren Sie dieMausdemo, in der die Klasse Kreis die Methode istdrinbesitzt. Beim Import erhalten Sie eine Meldung über einigeDateien, die nicht importiert werden konnten – klicken Sieeinfach auf „Weiter“.Löschen Sie jetzt die importierte Applet-Klasse MausDemo2 bzw.MausDemo3. Öffnen Sie den Kreis-Quelltext. Überprüfen Sie, ob er neben dem auf Seite 27dargestellten Text auch die Methode istdrin von Seite 31 enthält, andernfalls ergänzen Sie diesewenigen Zeilen.

Klassenvariablen und Instanzvariablen

Für dieses Spiel wird die Klasse Kreis noch leicht modifiziert: Den Radius r legen wir für alleQuadrate gleich fest, und zwar in einer einzigen gemeinsamen Variablen. Damit sich die Kreisenicht berühren, wird außerdem eine Randbreite rand festgelegt, die ebenfalls für alle Kreise gilt.Diese Variablen werden durch das Schlüsselwort static zu gemeinsamen Variablen – sieexistieren in der Klasse unabhängig davon, ob überhaupt eine Instanz (also ein Kreis) erzeugtwurde. Deshalb nennt man sie auch Klassen-variablen. Im Gegensatz dazu sind die in xund y gespeicherten Werte für den Mittelpunktdes Kreises für jeden Kreis individuell ver-schieden, sie werden für jede Instanz derKlasse Kreis neu angelegt und existieren nurinnerhalb der Instanzen. Solche Datenfelderheißen daher auch Instanzvariablen. Da dienoch zu erstellende Appletklasse auf denRadius und die Randbreite zugreifen, sind diestatischen Variablen als public deklariert.(Auch Methoden können als static deklariertwerden, hier ergibt sich dafür aber keinAnlass.)

Der Konstruktor wird angepasst, denn ihmwird jetzt kein Radius mehr übergeben, der istja bereits für alle Kreise mit dem Wert 40festgelegt.Die Farbe wird mit weiß initialisiert.

import java.awt.*;

/** * Klasse Kreis mit festem Radius * * @author Spier * @version Feb.2010 */public class Kreis{ public static int r = 40; public static int rand = 3; private int x, y; private Color farbe; /** * Konstruktor für Objekte der * Klasse Kreis * @param int x,y Mittelpunkt */ public Kreis(int x, int y) { this.x = x; this.y = y; farbe = Color.white; }

JAVA-Einführung, Seite 33

Die Methode zum Zeichnen muss den Rand berücksichtigen und wird ebenfalls angepasst:

In der Methode farbWechsel sorgen wir dafür,dass der Wechsel zwischen weiß und rotstattfindet.Damit sich später im Spiel leicht testen lässt, obbei allen Kreisen die Farbe rot erreicht ist,ergänzen wir noch eine Methode istRot.

Als letztes bearbeiten wir noch die Methode istdrin:

Die Kreisfläche hat nur noch den Radius (r-rand) und entsprechend wurde die Methode ange-passt. Jetzt ist die Klasse Kreis fertig programmiert.

Wir erstellen nun im Projekt 25erPuzzle die Appletklasse, der wir den Namen Puzzle geben.

ArrayEin Array speichert Zeiger für eine festgelegte Anzahl von Objekten des gleichen Typs. Hier könnenim Array dieKreise 25 Instanzen unserer Klasse Kreis verwaltet werden. dieKreise[0] ist dererste von ihnen und dieKreise[24] ist der letzte, die Zählung beginnt also bei 0.

/** * Diese Methode zeichnet die Kreisfläche mit dem Radius r-rand. * @param grafikObjekt für die Appletfläche */ public void zeichnen(Graphics grafikObjekt) { grafikObjekt.setColor(farbe); grafikObjekt.fillOval(x-r+rand,y-r+rand,2*(r-rand),2*(r-rand)); }

public boolean istRot() { return farbe == Color.red; }

public void farbWechsel(Graphics gr) { if (farbe == Color.white) farbe = Color.red; else farbe = Color.white; zeichnen(gr); }

public boolean istdrin(int u, int v) { return ((u-x)*(u-x) + (v-y)*(v-y) <= (r-rand)*(r-rand)); }

import java.awt.*;import javax.swing.*;import java.awt.event.*;

public class Puzzle extends JApplet{ // Ein Array von 25 Kreisen private Kreis[] dieKreise = new Kreis[25]; private MeinMausAdapter mma;

// Initialisierung des Applets public void init() { // "Workaround" ... JRootPane rootPane = this.getRootPane(); rootPane.putClientProperty("defeatSystemEventQueueCheck", true); // Mausadapter erzeugen: mma = new MeinMausAdapter();

Quelltext der Klasse Puzzle, Teil 1

Quelltext der Klasse Puzzle, Teil 1

JAVA-Einführung, Seite 34

For-SchleifeEine Schleife ist eine Programmstruktur, die mehrmals durchlaufen wird. For-Schleifen werdentypischerweise dann verwendet, wenn die Anzahl der Schleifendurchläufe von vornherein fest steht(beachten Sie aber auch den Hinweis zu Schleifen in Kapitel 9!). Dieser Schleifentyp besteht ausdem Schleifenkopf for (<Schleifenvariable mit Startwert>; <Wiederholungsbedingung>; <Änderungs-anweisung für die Schleifenvariable>)

und dem Schleifenkörper, der von geschweiften Klammern eingeschlossen ist.

Das Spielfeld hat 5 Zeilen und 5 Spalten mit Kreisen. Die Schleifen-variable i läuft von 0 bis 24. Der ganzzahlige Anteil von i/5 liefertbei den ersten 5 Durchläufen (i=0, 1, ... 4) den Wert 0 unddamit zeile = 0. Bei den nächsten 5 Durchläufen wird zeile = 1,dann 2 (usw.) und schließlich 4 (für 20/5 bis 24/5). Der Operator „%“ ist die Rechenanweisung für den Divisionsrest,die Ergebnisse für die Spalte sind bei den Schleifendurchläufen also0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 0, 1, ...

Beim 8. Schleifendurchlauf ist z.B. i=7, zeile = 1, spalte = 2.Der Kreis, der bei diesem Schleifendurchlauf erzeugt werden soll, istin der Abbildung mit einem Kreuz gekennzeichnet (Zeilen- undSpaltenzählung beginnen bei 0). Der Mittelpunkt hat die x-Koordinate 5×Radius. Damit auch dasSpielfeld einen Rand besitzt, wird noch die Randbreite addiert. Die y-Koordinate ergibt sichentsprechend zu 3×Radius + Randbreite. Die so berechneten Mittelpunktskoordinaten werden beijedem Schleifendurchlauf an den Konstruktor für den Kreis übergeben, und der erzeugte Kreis wirdder i-ten Position im Array (dieKreise[i]) zugewiesen. Wie im Kopf angegeben wird i am Endejedes Durchlaufs um 1 erhöht (i++ ist gleichbedeutend mit i = i + 1).

Damit ist die init-Methode abgeschlossen.

Start und StopDer Mausadapter mma wurde in der init-Methode erzeugt. Wenn er in der start()-Methode desApplets hinzugefügt und in der stop()-Methode wieder entfernt wird, funktionieren auch dieMenüpunkte „Neu starten“, „Starten“, „Abbrechen“ des Appletviewers. Probieren Sie es aus, wenndas Applet fertig programmiert ist! Auch wenn im Browser ein entsprechendes Menü nichtangezeigt werden kann, erscheint es sinnvoll, grundsätzlich wie folgt zu verfahren:

// 25 Kreise mit gewünschter Position erzeugen: for (int i = 0; i < 25; i++) { int zeile = i / 5; int spalte = i % 5; dieKreise[i] = new Kreis(Kreis.r*(2*spalte+1)+Kreis.rand, Kreis.r*(2*zeile+1)+Kreis.rand); } }

Quelltext der Klasse Puzzle, Teil 2

Quelltext der Klasse Puzzle, Teil 2

public void start() { addMouseListener(mma); }

public void stop() { removeMouseListener(mma); }

Quelltext der Klasse Puzzle, Teil 3

Quelltext der Klasse Puzzle, Teil 3

JAVA-Einführung, Seite 35

Die anschließend von BlueJ vorgeschlagene destroy()-Methode bleibt leer, sie kann gelöschtwerden. Kommen wir also zur paint-Methode:

Zunächst wird die Größe derAppletfläche ermittelt und in derlokalen Variablen r gespeichert,diese Fläche wird als Hintergrundmit einem leicht bläulich getöntemGrau gefärbt.Dann folgt eine for-Schleife: DerSchleifenkopf ist identisch mit demaus der init-Methode. Im Schlei-fenkörper wird für jeden im Arraygespeicherten Kreis dessen Metho-de zum Zeichnen aufgerufen.

Die abschließend aufgerufene Methode meldung() gibt einen Text aus und wird im folgendenAbsatz beschrieben:

Die lokale Variable gelöst wird zunächst auf true gesetzt, dann wird in einer while-Schleifegeprüft, ob vielleicht doch noch ein Kreis weiß ist. Abhängig vom Ergebnis wird unterhalb desSpielfeldes eine Rechteckfläche gefärbt und einer der beiden Texte ausgegeben.

While-SchleifeHier muss die Schleife nicht 25 mal durchlaufen werden, denn sobald ein weißer Kreis gefunden ist,steht fest, dass das Puzzle noch nicht gelöst ist. Die Schleife wird solange (=while) durchlaufen, wiegelöst wahr ist, und außerdem i<25 gilt. Nur wenn i=25 erreicht wird, ist das Puzzle gelöst.

Dieser Schleifentyp besteht aus dem Schleifenkopf while (<Wiederholungsbedingung>) und demSchleifenkörper, der von geschweiften Klammern eingeschlossen ist. Der Schleifenkörper wird

public void paint(Graphics g) { Rectangle r = getBounds(); g.setColor(new Color(200,200,220)); g.fillRect(r.x, r.y, r.width, r.height); for (int i = 0; i < 25; i++) { dieKreise[i].zeichnen(g); } meldung(); } Quelltext der Klasse

Puzzle, Teil 4

Quelltext der Klasse Puzzle, Teil 4

private void meldung() { boolean geloest = true; int a = 10*Kreis.r+2*Kreis.rand; // Spielfeld-Kantenlänge // while-Schleife: Anfang ---------------------------- int i = 0; while (geloest && i<25) { gelöst = dieKreise[i].istRot(); i++; } // while-Schleife: Ende --------------------- Graphics gr = getGraphics(); if (gelöst) { gr.setColor(new Color(230,255,200)); gr.fillRect(0, a, a, 22); gr.setColor(Color.black); gr.drawString("Puzzle gelöst, Glückwunsch!", 5, a+17); } else { gr.setColor(Color.blue); gr.fillRect(0, a, a, 22); gr.setColor(Color.white); gr.drawString("Klicken Sie, bis alle Kreise rot sind!",5,a+17); } }

Quelltext der Klasse Puzzle, Teil 5

Quelltext der Klasse Puzzle, Teil 5

JAVA-Einführung, Seite 36

solange immer wieder durchlaufen, bis die Wiederholungsbedingung nicht mehr erfüllt ist.Die in der Schleife verwendeten Variablen müssen vor Schleifenbeginn deklariert und initialisiertsein (i = 0), die Erhöhung des laufenden i erfolgt innerhalb des Schleifenkörpers (i++). Letztereswird leicht vergessen – dann hat man meistens eine „Totschleife“ programmiert, die nie verlassenwird, das Applet „hängt sich auf“ und muss „gewaltsam“ beendet werden!In Kapitel 9 können Sie nachlesen, wie while -Schleifen oft durch for -Schleifen ersetzt werdenkönnen!

Es folgt der letzte Teil des Applet-Quelltextes, der sich durch die Kommentare selbst erklärt:

Die Zeile und die Spalte des eventuell getroffenen Kreises ergeben sich durch Division von(Mauskoordinate – Rand) durch Kreisdurchmesser. Nachkommastellen werden bei der Zuweisungan eine Ganzzahl-Variable abgeschnitten. Aus Zeile und Spalte lässt sich leicht der Index des inFrage kommenden Kreises berechnen. Die Methode mousePressed ruft am Schluss meldung() auf,damit nach jedem Klick die Prüfung erfolgt, ob das Puzzle gelöst ist.

Rufen Sie das Applet mit einer Höhe von 434 und einer Breite von 406 (=5*Durchmesser+2*Rand)auf! Versuchen Sie Ihr Glück, nutzen Sie die Möglichkeit des Neustarts mit dem Menü des Applet-viewers! Viel Spaß beim Spielen!

Zum Weitergeben lassen Sie BlueJ die html-Seite erzeugen und bearbeiten Sie die DateiPuzzle.html mit dem Windows-Editor so, wie auf Seite 26 beschrieben. Der Anwender muss dieseDatei und die Dateien Puzzle.class, Kreis.class, Puzzle$MeinMausAdapter.class im selben Ordnerspeichern, um das Spiel im Browser ausführen zu können.

// Meine MausAdapter-Klasse mit mousePressed-Methode: private class MeinMausAdapter extends MouseAdapter { public void mousePressed(MouseEvent e) { int x = e.getX(); // Mausposition holen int y = e.getY(); // Zeile und Spalte ermitteln: int spalte = (x-Kreis.rand) / (2*Kreis.r); int zeile = (y-Kreis.rand) / (2*Kreis.r); // Index des Keises, der getroffen sein könnte: int nr = 5*zeile + spalte; // Wenn getroffen, dann Farbe wechseln: if (dieKreise[nr].istdrin(x,y) && e.getButton() == MouseEvent.BUTTON1) { Graphics gra = getGraphics(); dieKreise[nr].farbWechsel(gra); // Nachbarfeld-Farbwechsel, soweit nötig: if (spalte > 0) dieKreise[nr-1].farbWechsel(gra); if (spalte < 4) dieKreise[nr+1].farbWechsel(gra); if (zeile > 0) dieKreise[nr-5].farbWechsel(gra); if (zeile < 4) dieKreise[nr+5].farbWechsel(gra); } meldung(); } }} // abschließende Klammer der Klasse Puzzle

Quelltext der Klasse Puzzle, Teil 6

Quelltext der Klasse Puzzle, Teil 6

JAVA-Einführung, Seite 37

9. Was haben wir jetzt gelernt? (Wdh. und kleine Ergänzungen)Sie haben in den vorangegangenen Kapiteln Grundlagen der Programmiersprache JAVA kennengelernt. Hier können Sie zur Wiederholung nachlesen, wie ein JAVA-Quelltext aufgebaut ist:

Klassen: Jeder Quelltext definiert eine Klasse und hat folgende Form:

Instanzen der Klasse werden mit new <Klassenname>([Parameter]) erzeugt, siehe auch Konstruktor.Es ist üblich, Klassennamen mit einem Großbuchstaben zu beginnen.

Variablen werden in der Form

definiert, also indem zuerst der Typ und dann der Variablenname festgelegt werden, z.B. int a;oder String s = "Informatik"; oder double c = -3.08;

Für die Zugriffsberechtigung verwenden wir meistens private oder public, sie kann auch alsprotected festgelegt werden, sie darf auch fehlen.

Wenn der Typ eine Klasse ist, stellt die Variable genaugenommen einen Zeiger (eine Referenz) aufeine Instanz dieser Klasse dar. Es ist üblich, Variablennamen mit einem Kleinbuchstaben zubeginnen.

Methoden werden in folgender Form definiert:

Der Rückgabetyp gibt an, was die Methode liefert (einen String? Eine Gleitkommazahl?), sofern siedenn einen Wert zurück gibt. Bei Methoden ohne Rückgabewert muss hier void angegeben werden.Bei Methoden mit Rückgabewert muss der Methodenquelltext stets auf eine return-Anweisungführen. Die Parameterliste legt fest, welche Arten von Daten an die Methode übergeben werden sollen.Dabei wird immer erst der Typ, dann ein Variablenname genannt. Mehrere Parameter werden durchKomma getrennt. Beim Methodenaufruf werden Werte (oder Zeiger) an die Methode übergeben, dieMethode verwendet gemäß Parameterliste lokale Variablen, um mit diesen Werten zu arbeiten. DieParameterliste darf auch leer sein, die Klammern müssen dann trotzdem stehen.

Ein Beispiel: Die Lösung von Aufgabe 17 auf Seite 20 (ganz ähnlich ist die Lösung von Aufgabe24).

public void setName(String v, String n)

{

vorname = v; // Datenfeld vorname erhält Wert der lokalen Variablen v,

nachname = n; // nachname erhält entsprechend Wert von n.

}

<Import-Anweisungen soweit erforderlich>

public class <Klassenname> [optional: extends <Vorgängerklasse>]

{

<Bereitstellung von Variablen (Instanzvariablen / Klassenvariablen>

<Methoden (auch der Konstruktor ist eine Methode)>

[optional: weitere Klassendefinition, z.B. MausAdapter]

}

<Zugriffsberechtigung><Typ> <Name> [optional: Wertzuweisung];

<Zugriffsberechtigung> <Rückgabetyp> <Name>(<Parameterliste>){

<Methodenquelltext, bei Bedarf mit Bereitstellung von lokale Variablen>

[ggf. return-Anweisung]

}

JAVA-Einführung, Seite 38

Es ist üblich, Methodennamen mit einem Kleinbuchstaben zu beginnen.Ein Beispiel für die Verwendung von lokalen Variablen, die erst innerhalb der Methode definiertwerden, zeigt die Klasse „Bank“ in ihrer Methode überweisen. Der für die lokalen Variablenreservierte Speicherplatz wird mit Abschluss der Methode frei gegeben, diese Variablen existierendann nicht mehr.

Es können mehrere Methoden mit demselben Namen definiert werden, wenn sie sich in denParameterlisten unterscheiden (Vergl. Konstruktoren).

Konstruktoren sind spezielle Methoden, deren Syntax geringfügig von der zuvor beschriebenenabweicht. Sie werden in der Form

definiert. Die Zugriffsberechtigung ist meistens public. Da der Methodenname hier mit demKlassennamen übereinstimmt, wird für die Rückgabe kein Typ genannt, es gibt auch keine return-Anweisung: Der Aufruf erfolgt mit dem Schlüsselwort new und damit wird eine Instanz dieserKlasse (genau genommen: ein Zeiger darauf) zurückgegeben.Eine Klasse kann mehrere Konstruktoren besitzen. Wird kein Konstruktor programmiert, so kannder geerbte Konstruktor mit leerer Parameterliste zum Erzeugen von Instanzen verwendet werden.

Zugriff auf Daten / Methoden anderer Objekte:

Für den Zugriff auf Methoden oder Variablen, die nicht Teil der aktuellen Instanz sind, wird derBezeichner des Objekts (z.B. eines Bankkontos, eines Kreises, einer Graphics-Instanz) vorangestelltund ein Punkt als Trennzeichen gesetzt. Beispiel: dieKreise[i].zeichnen(g);

ProgrammstrukturenFallunterscheidungen werden mit if bzw. mit if ... else programmiert, die Form ist:

Der else-Teil istoptional, das heißt,er darf fehlen.

Wenn der Quelltext eines dieser Fälle nur aus einer einzigen Anweisung besteht, dürfen dessengeschweiften Klammern fehlen.Eine ergänzende Anmerkung: Da die return-Anweisung eine Methode sofort beendet, darf bei derAltersberechnung der Klasse „Person“ das else fehlen:if (hatteSchonGeburtstag)

return heute.get(Calendar.YEAR)–geburtsDatum.get(Calendar.YEAR); //Schluss!

return heute.get(Calendar.YEAR) - geburtsDatum.get(Calendar.YEAR) - 1;

Das erste return wird erreicht, wenn hatteSchonGeburtstag wahr ist, sonst das zweite. BildenSie sich selbst ein Urteil über die Verständlichkeit eines solchen Quelltextes.Für Fallunterscheidungen mit mehr als zwei Fällen kann die switch-Anweisung hilfreich sein, aufdie aber in diesem Text nicht eingegangen wird.

<Zugriffsberechtigung> <Klassenname>(Parameterliste){

<Konstruktorquelltext> // Initialisierung

}

if (<Bedingung>)

{

<Quelltext für Wenn-Fall>

}

else

{

....<Quelltext für Sonst-Fall>

}

JAVA-Einführung, Seite 39

SchleifenSyntax der for-Schleife:for (<Schleifenvariable mit Startwert>; <Wiederholungsbedingung>; <Änderungsanweisung für dieSchleifenvariable>) {<zu wiederholende Anweisungen>}

Die Schleifenvariable kann innerhalb der runden Klammer deklariert werden, dann ist sie nur inner-halb der Schleife gültig. Sie kann aber auch schon vorher definiert sein, dann kann ihr (veränderter)Wert nach Verlassen der Schleife weiter verwendet werden.

Syntax der while-Schleife:while (<Wiederholungsbedingung>) {<zu wiederholende Anweisungen>}

Bei diesem Schleifentyp müssen die zu wiederholenden Anweisungen dafür sorgen, dass dieWiederholungsbedingung nicht dauerhaft erfüllt bleibt!

Beispiel: Die while-Schleife in der Methode meldung() aus dem Quelltext der Klasse Puzzle(S. 35) kann elegant durch folgende for-Schleife ersetzt werden:

for (int i = 0; geloest && i<25; i++) // Abbruch, wenn Kreis nicht rot ist!

{

geloest = dieKreise[i].istRot();

}

10. SchlussbemerkungBlueJ ist für die hier vorgestellten Projekte eine gut geeignete Entwicklungsumgebung, insbe-sondere durch die Möglichkeit, Instanzen zu „inspizieren“ und ihre Methoden ohne Program-mierung eines Menüs aufrufen zu können. Auch der Zugriff einer Instanz auf eine andere Instanz(Projekt „Bank“) lässt sich gut demonstrieren. Für den Einstieg in JAVA ist BlueJ daher eine guteWahl.

Andere Entwicklungsumgebungen haben andere Vorteile, sie bieten z.B. Unterstützung bei derLayout-Gestaltung eines Applets, sie erlauben den bequemen Einbau eines Menüs oder vonSchaltflächen für Programmaktionen. Beispiele sind die Programme „Java-Editor“ und „NetBeans“,die wie BlueJ ebenfalls kostenlos aus dem Internet heruntergeladen werden können.Beide Programme bieten auch eine Code-Vervollständigung an: Wenn man in diesen Entwicklungs-umgebungen bei unserem Puzzle-Quelltext (Kapitel 8) den Klassenbezeichner „Kreis.“ eintippt,wird sofort die Auswahl der möglichen Methoden oder Variablen angezeigt, die in dieser Klasseverfügbar (also public) sind. Dieser Vorteil zeigt sich auch z.B. bei der Verwendung eines Graphics-Objektes: Sobald man den Bezeichner und den anschließenden Punkt getippt hat, kann man schonsehen, welche Methoden dieses Objekt besitzt (drawrect, fillrect, drawtext usw.) – außerdemwerden die benötigten Parameter angezeigt. Dadurch kann man sich oft das Nachlesen in der Doku-mentation zu den verwendeten Klassen ersparen.

Das Programm „Java-Editor“ beansprucht deutlich weniger Ressourcen als „NetBeans“ und ist zumErstellen kleiner Programme gut geeignet. Automatisch erstellter Quelltext kann jedoch soverändert werden, dass es zu Unstimmigkeiten zwischen Layout-Entwurf und Aussehen desProgramm-Fensters kommen kann. „NetBeans“ hat dagegen ein so umfangreiches Menü, dassAnfänger es schon beim Erstellen und Speichern ihres ersten Projekts schwer haben; dieseEntwicklungsumgebung ist sehr professionell und eignet sich gut für komplexe Anwendungen.

Je anspruchsvoller Programme werden, umso mehr zeigen sich die Vorteile der hier genanntenEntwicklungsumgebungen.

While-Schleifen können oft durch for-Schleifen ersetzt werden, weil die Wiederholungs-bedingung auch unabhängig von der Schleifenvariablen formuliert werden kann, sie kannauch eine Kombination mehrerer Bedingungen sein.

JAVA-Einführung, Seite 40

Deshalb wird dieseEinführung in die JAVA-Programmierung

mit BlueJhier beendet.

(Es folgt nur noch ein kleiner Anhang.)

Anhang

JAVA-Programm ohne Entwicklungsumgebung erstellenAuch ohne Entwicklungsumgebung ist es möglich, ein JAVA-Programm zu schreiben. Jeder Editorist dafür geeignet – wichtig ist nur, dass der Quelltext als reiner Text gespeichert ist. Der einfachsteEditor ist der Windows-Editor, der ohnehin nur im Textformat speichern kann, da er keineTexthervorhebungen und Absatzformate zulässt.Starten Sie den Editor und schreiben Sie den folgenden Text:import javax.swing.*;

import java.awt.*;

public class HalloWelt extends JApplet

{

public void paint(Graphics g)

{

g.setColor(new Color(190,230,255)); // Farbe aus RGB erzeugen

g.fillRect(0,0,150,30); // Rechteckfäche färben

g.setColor(Color.BLUE); // blau

g.drawString("Hallo Welt!",50,25); // Text ausgeben

}

}

JAVA-Einführung, Seite 41

Speichern Sie diesen Text unter dem Namen "HalloWelt.java" – dazu müssen Sie die Anführungs-zeichen mit eingeben, damit der Editor nicht HalloWelt.java.txt daraus macht.Jetzt muss dieser Text compiliert werden. Dazu öffnen Sie ein Fenster mit der DOS-Eingabeaufforderung (Start-Programme-Zubehör-Eingabeaufforderung). Mit diesem Kommando-zeilenfenster muss der Java-Compiler aufgerufen werden, wobei zugleich als Parameter die zucompilierende Datei angegeben sein muss. Der Compiler heißt javac.exe und befindet sich im bin-Ordner des Java-Development-Kits, so dass der Befehl wie abgebildet lauten könnte:

Bei Quelltext-Fehlern erhalten Sie Hinweise, andernfalls wird die Datei HalloWelt.class erzeugt.Diese ist nicht direkt ausführbar, kann aber als Applet in einer Html-Seite ausgeführt werden. Umdiese Html-Seite zu erstellen, kann wieder der Windows-Editor verwendet werden. Schreiben Sieeine Datei mit folgendem Text:

<html>

<head>

<TITLE>Hello World mit JAVA</TITLE>

</head>

<body>

Hier folgt der Output des Programms:<br>

<APPLET CODE="HalloWelt.class" width=150 height=30>

</APPLET>

</body>

</html>

Speichern Sie diese Datei als "Hallo.html" (Anfüh-rungszeichen beachten, s.o.). Die class-Datei und die html-Datei müssen sich im selben Verzeichnisbefinden. Anschließend öffnen Sie die html-Datei durch Doppelklick.

Das Java-Development-Kit bietet auch die Möglichkeit, das Applet ohne Browser anzusehen. Dazumuss der Appletviewer aufgerufen werden, als Parameter wird die Html-Seite übergeben (in der dieApplet-Maße vermerkt sind):

Erst, wenn Sie das Applet beenden, können Sie im Kommandozeilen-fenster weitere Anweisungen eingeben (z.B. exit). Der Aufruf des Applet-viewers ist in BlueJ zum Anzeigen von Applets integriert.

Listen, die nur Instanzen einer einzigen Klasseverwalten

Im Projekt Bank_2 lernten Sie die Klasse ArrayList kennen, die untypisierte Zeiger speichert. DieMethode get(...) dieser Klasse lieferte keine Konto-Instanzen, deshalb musste eine Typumwandlungerfolgen, um aus dem Zeiger einen Kontozeiger (ein Konto) zu machen (siehe Seite 13). Der BlueJ-Compiler lieferte eine Warnmeldung (die man unter 'Einstellungen' abschalten kann).Diese Warnmeldung entfällt, wenn wir eine Liste verwenden, die nur Konto-Instanzen enthalten

JAVA-Einführung, Seite 42

kann, außerdem ist dann keine Typumwandlung mehr nötig. Die Liste wird für das Bank_2-Projektdann wie folgt als typisierte Liste deklariert:

private LinkedList<Konto> kontoListe;

Die Syntax mit spitzen Klammern verweist immer auf einen Typ. Eine LinkedList verwaltet außerden Daten auch Methoden zum Auffinden des Vorgängers und Nachfolgers, sie ist daher vielseitigerals eine ArrayList (bei der ebenso der Typ angegeben werden kann). Von dieser Liste wird nun eineInstanz erstellt:

kontoListe = new LinkedList<Konto>();

Die Methode findByNumber kann unter Verwendung einer for-Schleife (mit Abbruchbedingung beigefundenem Konto, vergl. Seite 39) kurz und – wie gesagt: ohne Typumwandlung – so geschriebenwerden: private Konto findByNumber(int ktoNr) { Konto kt = null; for (int i=0; i<kontoListe.size() && kt==null; i++) { if (kontoListe.get(i).getKontoNummer() == ktoNr) kt = kontoListe.get(i); } return kt; }

Formatierungen von numerischen Werten

Datumswerte werden als Zahl gespeichert. Die Umwandlung von Zahlen in einen String ist mit derstatischen Methode format der Klasse String möglich. Dabei gibt der erste Parameter an, wie dienachfolgenden Daten formatiert werden sollen, anschließend folgen ein oder mehr Parameterunterschiedlicher (auch nichtnumerischer) Typen, deren Werte zu einem String formatiert werdensollen. Die Möglichkeiten sind sehr umfangreich, ausführliche Information liefern die Java-Klassenbliotheken. Hier werden nur 2 Beispiele genannt.

Währungsausgabe in Euro: System.out.println(String.format("Rückgeld = %.2f €",wechselGeld));

„%“ kennzeichnet, dass hier Daten formatiert eingesetzt werden sollen, „.2“ kennzeichnet beiFließkommazahlen die Anzahl der Nachkommastellen, „f“ steht für das Formatieren eine Fließ-kommazahl.Bei der Ausgabe des Strings mit System.out können Sie diese Zeile vereinfachen zu System.out.printf("Rückgeld = %.2f €\n",wechselGeld);

(printf verwenden dieselbe format-String-Syntax wie String.format. Mit \n wird einZeilenumbruch erzeugt, damit diese Zeile dasselbe wie oben mit println leistet.)

Datum im Format „Wochentag, tt.mm.jjjj“ (vergl. Kapitel 5): String.format("Geboren: %1$tA, %1$td.%1$tm.%1$tY",geburtsDatum);

geburtsDatum ist eine GregorianCalendar-Instanz, format wertet deren Zeit-Informationen aus.

-------------------------------------------------------------------------------------------------------------Ende.