© APSIS GmbH |
Seite 18
Seite 18
public class LeereKlasse // (2.1) { // dies ist eine leere Klasse }
public class ZweiteLeereKlasse {} /* Diese Klasse ist auch leer */
javac LeereKlasse.java
java LeereKlasse
Abb. 2.1: Übersetzen und interpretieren einer Klasse
av LeereKlasse
Übung 2.1: Geben Sie der leeren Klasse einen anderen Namen, und tippen Sie sie mit Hilfe des Editors in Ihren Rechner ein. Speichern Sie sie in einer Datei, geben Sie dabei auch der Datei einen geeigneten Namen (denselben wie Ihrer Klasse, mit der Dateinamenergänzung .java). Übersetzen Sie sie mit Ihrem Compiler. Falls er infolge von Tippfehlern Fehler meldet, korrigieren Sie sie mit dem Editor, bis Sie eine Datei mit dem Bytecode bekommen. Versuchen Sie diese mit den Interpretern java und av auszuführen. Die Ausführung wird allerdings ähnlich wie bei der Klasse LeereKlasse im Programm (2.1) auf Seite 18 von beiden Interpretern mit einer Fehlermeldung abgelehnt.
Seite 20
Seite 20
public class AuchLeer extends LeereKlasse // (2.2) ¬ { // Dies ist auch noch eine leere Klasse. }
Abb. 2.2: Erweiterung von Klassen
Übung 2.2: Erweitern Sie Ihre leere Klasse aus der Übung 2.1 auf Seite 20. Übersetzen Sie sie und versuchen Sie sie mit zwei verschiedenen Interpretern auszuführen. Beobachten Sie das Ergebnis.
Seite 21
public class NochmalLeer extends lehrbuch.LeereKlasse // (2.3) ¬ // LeereKlasse aus dem Paket lehrbuch wird erweitert { // Dies ist immer noch eine leere Klasse. }
Abb. 2.3: Paket als Namensraum
Übung 2.3: Lesen Sie die Programmtextdatei, die Sie in der Übung 2.2 auf Seite 21 erstellt haben, in Ihren Editor ein. Geben Sie der Klasse einen anderen (selbsterfundenen) Namen, und erweitern Sie damit die Klasse Programm aus dem Paket lehrbuch. Speichern Sie Ihr Programm unter einem geeigneten Dateinamen.
Beim Übersetzen des Programms werden Sie möglicherweise feststellen, dass der Compiler das Paket lehrbuch nicht kennt. Sie müssen es dem Compiler bekannt geben. Das tun Sie, indem Sie auf Ihre Festplatte kopieren und den Ort entsprechend der Bedienungsanleitung Ihres Compilers hinzufügen. Bei javac besteht dies aus dem Setzen der Umgebungsvariable CLASSPATH.
Diesmal ist der Interpreter av in der Lage, die Klasse auszuführen; das Ergebnis zeigt allerdings nur ein leeres Fenster.
Seite 22
public class NichtMehrLeer extends lehrbuch.Programm // (2.4) ¬ { // Klasse ist nicht mehr leer; sie enthält, was sie von der Klasse Programm geerbt hat. }
javac NichtMehrLeer.java
av NichtMehrLeer
Seite 23
public class HalloWelt extends lehrbuch.HalloWelt // (2.5) ¬ { }
Abb. 2.4: Animation
Übung 2.4: Erweitern Sie die Klasse JavaIstSpitze aus dem Paket lehrbuch durch Ihre eigene Klasse (diese können Sie z.B. Spitze nennen) und überprüfen ihre Wirkung, indem Sie sie mit av interpretieren.
Seite 23
public class ZweitesHallo extends HalloWelt {} // (2.6)
Abb. 2.5: Mehrfache Erweiterung
Seite 24
public class KeinHallo extends lehrbuch.HalloWelt // (2.7) { public void start() // Methode aus lehrbuch.HalloWelt wird überschrieben ¬ { // dies ist eine leere Methode } }
Abb. 2.6: Überschreiben von Methoden
Abb. 2.7: Profil einer Methode
Abb. 2.8: Definition einer Methode
Übung 2.5: start ist nicht die einzige Methode der Klasse lehrbuch.HalloWelt, die überschrieben werden kann. Überschreiben Sie die Methode init mit der leeren Methode und vergleichen Sie die Wirkung mit der Version, wo start überschrieben wurde. Rufen Sie in einem zweiten Programm die Methode gutenMorgen der Klasse lehrbuch.HalloWelt in der überschriebenen init auf.
Seite 25
public class JavaIstSpitze extends lehrbuch.HalloWelt // (2.8) { public void start() // Methode aus lehrbuch.HalloWelt wird überschrieben { super.javaIstSpitze(); // kleingeschrieben, im Gegensatz zum Klassennamen ¬ // Aufruf der Methode javaIstSpitze aus der Oberklasse lehrbuch.HalloWelt } }
javaIstSpitze(); // Aufruf der Methode javaIstSpitze aus lehrbuch.HalloWelt ¬
Abb. 2.9: Aufruf von geerbten Methoden
javaIstSpitze(); // ein Aufruf ... javaIstSpitze(); // ein weiterer Aufruf derselben Methode
Übung 2.6: Bei der Klasse lehrbuch.HalloWelt besteht die Möglichkeit, statt javaIstSpitze die Methode halloWelt aufzurufen. Probieren Sie beide Möglichkeiten aus, indem Sie zwei (ähnliche) Programme schreiben: Die erste Version soll wie das obige Programm JavaIstSpitze sein. In der Zweiten rufen Sie nicht die Methode super.javaIstSpitze, sondern die Methode super.halloWelt auf. Das Ergebnis wird wie im Programm (2.5) auf Seite 23 sein.
Seite 27
public class HalloSpitze extends lehrbuch.HalloWelt { // (2.9) public void neueMethode() { ¬ super.javaIstSpitze(); // oder ein anderer Algorithmus } }
public class ZweiteSpitze extends HalloSpitze { // (2.10) public void start() { ¬ super.neueMethode(); // Aufruf der zuvor hinzugefügten Methode } }
Abb. 2.10: Hinzufügen von Methoden
Abb. 2.11: Definition und Aufruf von Methoden
Seite 28
public class PrivateMethode extends lehrbuch.HalloWelt { // (2.11) public void privateMethode() { // Definition der privaten Methode ¬ super.javaIstSpitze(); // javaIstSpitze aus lehrbuch.HalloWelt } public void start() { // Methode aus lehrbuch.HalloWelt wird überschrieben this.privateMethode(); // Aufruf der privaten Methode ¬ } }
Übung 2.7: Überarbeiten Sie eine der Klassen (Ihrer Wahl) aus der vorherigen Übung 2.6 auf Seite 26, indem Sie in der Methode start eine private Methode aufrufen. Hierin müssen Sie dann eine geerbte Methode aufrufen.
Seite 29
public class JesusLebt extends lehrbuch.HalloWelt { // (2.12) public void start() { // Methode aus lehrbuch.HalloWelt wird überschrieben super.animation("Jesus lebt!"); // Zeichenkettenparameter ¬ } }
protected void animation(String text) // Profil aus dem Quelltext HalloWelt.java
Übung 2.8: Benutzen Sie die Methode animation aus der Klasse lehrbuch.HalloWelt, um Ihren Lieblingsspruch zu animieren.
Übung 2.9: Die Methode abspielen aus der Klasse lehrbuch.HalloWelt ist geeignet, den Inhalt einer Audiodatei hörbar zu machen. Hierzu muss ihr Name als Zeichenkettenparameter der Methode übergeben werden.
Erweitern Sie nun lehrbuch.HalloWelt und hören Sie sich die Datei hallo.au aus der Lehrbuchbibliothek an oder eine beliebige andere Audiodatei, die Sie vielleicht erstellt (z.B. über eine Audiokarte mit dem Mikrofon aufgenommen), aus dem Internet geholt oder irgendwo gefunden haben.
Seite 30
public class TFHBerlin extends lehrbuch.HalloWelt { // (2.13) public void start() { super.animation("Technische", "Fachhochschule", "Berlin"); ¬ // drei Zeichenketten werden animiert } }
public void animation(String text)
public void animation(String text1, String text2, String text3)
Übung 2.10: Die Methode abspielen aus der Übung 2.9 kann auch mit zwei Parametern aufgerufen werden: Die Erste ist nach wie vor der Name einer Audiodatei; die Zweite ist eine Zeichenkette, die parallel zum Abspielen als Animation auf dem Bildschirm angezeigt wird. Ein Beispiel für den Aufruf ist etwa
abspielen("hallo.au", "Hallo Welt!");
Rufen Sie nun diese Methode mit Parametern Ihrer Wahl auf.
Seite 30
public class SpitzeAusKlasse extends lehrbuch.Programm { // (2.14) public void start() { // Methode aus lehrbuch.Programm wird überschrieben lehrbuch.HalloWelt.javaIstSpitze(); // Aufruf aus der Klasse HalloWelt ¬ } }
Seite 31
import lehrbuch.Programm; // (2.15) import lehrbuch.HalloWelt; public class SpitzeMitImport extends Programm { // Paket muss nicht genannt werden ¬ public void start() { HalloWelt.javaIstSpitze(); // Paket muss nicht genannt werden ¬ } }
import lehrbuch.*; // alle Klassen aus dem Paket lehrbuch können benutzt werden
Seite 31
javadoc lehrbuch.HalloWelt
package lehrbuch; // (2.16) ¬ public class HalloWelt { // Klasse zum erweitern (Applet) für Animation ¬ /** wenn nichts überschrieben, begrüßt die Welt mit einer Animation "Hallo Welt!" */ public void start(); // wird zu Beginn aufgerufen; führt Animation aus protected static void halloWelt(); // führt Animation "Hallo Welt!" aus protected static void animation(String text); protected static void animation(String text1, String text2, String text3); protected static void abspielen(String audiodateiname); protected static void abspielen(String audiodateiname, String text); public static void javaIstSpitze(); // führt Animation "Java ist Spitze!" aus ... // weitere Komponenten der Klasse }
Seite 33
Abb. 2.12: Datenbehälter
Seite 33
public class EimerZeigen extends lehrbuch.EinEimer { // (2.17) ¬ // diese Klasse stellt einen Eimer zur Verfügung }
Übung 2.11: Testen Sie das Programm (2.17), indem Sie es eintippen, übersetzen und ausführen. Sie werden einen Datenbehälter im Fenster betrachten können: Das Programm selbst führt allerdings keine Operationen aus, es hat nach wie vor einen leeren Anweisungsteil und implementiert ein konstantes Programm.
Seite 34
Abb. 2.13: Datenbehälter mit Operationen
Seite 35
Seite 35
public class EimerFuellen extends lehrbuch.EinEimer { // (2.18) public void start() { fuellen(); // Aufruf des Mutators aus der Klasse lehrbuch.EinEimer ¬ } }
Seite 36
Klasse.methode();
public class EimerProgramm extends lehrbuch.Programm { // (2.19) public void start() { lehrbuch.EinEimer.fuellen(); // Aufruf des Mutators aus lehrbuch.EinEimer ¬ } }
Seite 36
import lehrbuch.EinEimer; // (2.20) public class EimerSequenz extends lehrbuch.Programm { public void start() { EinEimer.fuellen(); // erstes Glied der Sequenz ¬ EinEimer.entleeren(); // zweites Glied der Sequenz ¬ } }
Übung 2.12: Verlängern sie den obigen Algorithmus EimerSequenz, indem Sie den Eimer dreimal nacheinander füllen und entleeren.
Seite 37
import lehrbuch.EinEimer; // (2.21) public class DynamischesEnde extends lehrbuch.Programm { public void start() { EinEimer.fuellen(); EinEimer.entleeren(); return; // die Ausführung der Methode wird abgeschlossen ¬ EinEimer.fuellen(); // Anweisung wird nicht mehr ausgeführt EinEimer.entleeren(); } } // statisches Ende ¬
Seite 38
import lehrbuch.EinEimer; // (2.22) public class EimerFehler extends lehrbuch.Programm { public void start() { EinEimer.fuellen(); EinEimer.entleeren(); EinEimer.entleeren(); // Fehler ¬ EinEimer.fuellen(); // wird nicht mehr ausgeführt } }
Seite 38
public class FehlerAbfangen extends lehrbuch.Programm { // (2.23) public void start() { try { // Anweisungen für den Normalfall ¬ lehrbuch.EinEimer.entleeren(); // Fehler, da der Eimer zu Anfang leer ist lehrbuch.EinEimer.entleeren(); // wird nicht mehr ausgeführt } catch (lehrbuch.LeerFehler ausnahme) { // ¬ // Anweisungen für den Fehlerfall; hier gar keine } } }
Seite 39
public void fuellen(); // darf am Anfang oder nach entleeren aufgerufen werden, sonst Ausnahme LeerFehler public void entleeren(); // darf nur nach fuellen aufgerufen werden, sonst Ausnahme VollFehler
Übung 2.13: Untersuchen Sie diese Klasse anhand ihrer Spezifikation in der Datei ToleranterEimer.spec und schreiben Sie ein Programm, das zeigt, dass sie wirklich fehlertolerant ist.
Seite 39
public class Verteiler extends lehrbuch.Programm { // (2.24) public void start() { try { ... // entleeren und fuellen gemischt } catch (lehrbuch.LeerFehler ausnahme) { // ¬ super.meldung("Eimer leer!"); // oder irgendwelche Aktion für den Fehlerfall } catch (lehrbuch.VollFehler ausnahme) { // ¬ super.meldung("Eimer voll!"); } } }
Seite 40
public class EinEimer { public static void fuellen() throws VollFehler; // ¬ public static void entleeren() throws LeerFehler; // ¬ ...
Seite 40
import lehrbuch.ZweiEimer; // (2.25) public class LinksRechts extends lehrbuch.Programm { public void start() { try { ZweiEimer.fuellenLinks(); // kann VollAusn auslösen ¬ ZweiEimer.fuellenRechts(); // kann VollAusn auslösen ZweiEimer.entleerenRechts(); // kann LeerAusn auslösen ¬ ZweiEimer.entleerenLinks(); // kann LeerAusn auslösen } catch (lehrbuch.LeerAusn ausnahme) { // ¬ super.meldung("Eimer leer!"); } catch (lehrbuch.VollAusn ausnahme) { // ¬ super.meldung("Eimer voll!"); } } }
import lehrbuch.*; // (2.26) public class EimerMitFehler extends Programm { // aus dem Paket lehrbuch public void start() { try { ZweiEimer.anzeigenLinks(); ZweiEimer.fuellenLinks(); // sichtbar ZweiEimer.fuellenRechts(); // unsichtbar ZweiEimer.anzeigenRechts(); // voller Eimer wird sichtbar ZweiEimer.entleerenLinks(); // sichtbar ZweiEimer.fuellenRechts(); // Fehler, wird unterbrochen ¬ ZweiEimer.anzeigenLinks(); // wird nicht mehr ausgeführt } catch (LeerAusn ausnahme) { // aus dem Paket lehrbuch ¬ super.meldung("Eimer leer!"); // aus der Oberklasse lehrbuch.Programm } catch (VollAusn ausnahme) { // ¬ super.meldung("Eimer voll!"); } } }
Seite 42
public class NichtWeiterreichen extends lehrbuch.Programm { // (2.27) public void privateMethode() { // exportiert keine Ausnahme ¬ try { lehrbuch.ZweiEimer.fuellenLinks(); // throws VollAusn // Ausnahme muss aufgefangen werden: } catch (lehrbuch.VollAusn ausnahme) { meldung("Eimer voll!"); // Ausnahme behandelt, wird nicht weitergereicht } } public void start() { privateMethode(); // geht gut privateMethode(); // keine Ausnahme wird ausgelöst meldung("Programmende"); // Meldung erscheint } }
public class Weiterreichen extends lehrbuch.Programm { // (2.28) public void privateMethode() throws lehrbuch.VollAusn { // ¬ // Ausnahme wird weitergereicht, hier kein try nötig lehrbuch.ZweiEimer.fuellenLinks(); // throws VollAusn, wird weitergereicht } public void start() { try { privateMethode(); // throws VollAusn, geht gut privateMethode(); // throws VollAusn // Ausnahme muss hier aufgefangen werden; Sequenz wird unterbrochen meldung("Programmende"); // Meldung erscheint nicht mehr } catch (lehrbuch.VollAusn ausnahme) { meldung("Eimer voll!"); } finally { // Option ¬ meldung("Endlich!"); // Anweisung wird auf jeden Fall ausgeführt } } }
Übung 2.14: Modifizieren Sie Ihre Lösung der Übung 2.12 auf Seite 37, indem Sie darin eine Ausnahme auslösen. Beobachten Sie und markieren Sie mit einem Kommentar, welche Aufrufe ausgeführt werden und welche nicht mehr. Fangen Sie in einem zweiten Programm die Ausnahmen VollFehler und LeerFehler auf. Rufen Sie im Ausnahmebehandlungsteil die Methode meldung aus der Klasse lehrbuch.Programm auf. Sie verlangt einen Zeichenkettenparameter: Melden Sie jeweils "Eimer voll!" oder "Eimer leer!". Schreiben Sie auch einen finally-Block: Melden Sie hier, dass das Programm beendet ist.
Übung 2.15: Untersuchen Sie die Spezifikation der Klasse lehrbuch.VierKreise und schreiben Sie ein Programm, das die Operationen der durch sie implementierten statischen Objekte testet.
Seite 43
Seite 43
Eimer eimer; // Eimer ist die Klasse, eimer ist die Referenz
eimer = new Eimer(); // ein Objekt wurde erzeugt; es wird von eimer referiert
Abb. 2.14: Referenz und Objekt
Seite 44
import lehrbuch.*; // (2.29) public class ZweiObjekte extends Programm { public void start() { try { Eimer linkerEimer, rechterEimer; // zwei Referenzen ¬ linkerEimer = new Eimer(); // ein Objekt erzeugt ¬ rechterEimer = new Eimer(); // ein zweites Objekt erzeugt linkerEimer.anzeigen(); // Methodenaufruf für das erste Objekt ¬ rechterEimer.anzeigen(); // Methodenaufruf für das zweite Objekt linkerEimer.fuellen(); rechterEimer.fuellen(); linkerEimer.entleeren(); rechterEimer.entleeren(); } catch (VollAusn ausnahme) { meldung ("Eimer schon voll"); // aus der Klasse Programm } catch (LeerAusn ausnahme) { meldung ("Eimer noch leer"); } } }
Seite 45
Eimer ersterEimer, zweiterEimer, dritterEimer, vierterEimer; // (2.30) ersterEimer = new Eimer(); // ein Objekt ... // weitere Objekte können erzeugt werden
Eimer eimer; // eine Referenz, kein Objekt eimer.anzeigen(); // Ausnahme wird ausgelöst ¬
Eimer eimer; // eine Referenz eimer = new Eimer(); // ein Objekt wurde erzeugt eimer.anzeigen(); // Methode wird aufgerufen eimer.fuellen(); eimer = new Eimer(); // ein zweites Objekt wurde erzeugt
Eimer eimer = new Eimer();
Übung 2.16: Das Paket lehrbuch exportiert (unter anderen) auch die Klasse Kreis (für dynamische Objekte). Legen Sie nun zwei Kreise an. Mit ihrer Operation zeichnen können Sie einen Kreis im Fenster sichtbar machen. Der Mutator bemalen färbt denjenigen Kreis, welchen Sie ihm als Zielobjekt angeben. Rufen Sie den Mutator bemalen für einen Kreis wiederholt auf, erhält er eine neue Farbe. Mit dem Mutator verstecken wird Ihr Kreis unsichtbar. Ein anschließender Aufruf von zeichnen lässt ihn wieder erscheinen, allerdings farblos. Der Mutator wiederherstellen bringt ihn in derselben Farbe auf den Bildschirm, in der er versteckt wurde.
Abb. 2.15: Datenbehälter Kreis
Seite 47
Eimer eimer1, eimer2; // (2.31) eimer1 = new Eimer(); // Objekt wird erzeugt eimer2 = eimer1; // Objekt referiert durch zwei Referenzen ¬
Abb. 2.16: Zwei Referenzen auf ein Objekt
eimer1.fuellen(); // Objekt wird gefüllt eimer2.entleeren(); // dasselbe Objekt wird entleert
Seite 47
Klasse1 referenz1 = new Klasse1(); // (2.32) Klasse2 referenz2 = new Klasse2(); referenz1.methodeAusKlasse1(); // passt referenz2.methodeAusKlasse2(); // passt referenz2.methodeAusKlasse1(); // Typfehler ¬ referenz2 = new Klasse1(); // ebenfalls Typfehler
Seite 48
import lehrbuch.*; // (2.33) public class GlobaleReferenz extends Programm { private Eimer eimer; // globale Referenz ¬ private void privateMethode() throws VollAusn, LeerAusn { eimer.fuellen(); eimer.entleeren(); } public void start() { try { eimer = new Eimer(); // ein Objekt erzeugt ¬ eimer.anzeigen(); // Methodenaufruf für das erzeugte Objekt ¬ eimer.fuellen(); // ¬ eimer.entleeren(); privateMethode(); } catch (VollAusn ausnahme) { meldung("Eimer schon voll"); } catch (LeerAusn ausnahme) { meldung("Eimer noch leer"); } } ... // evtl. weitere Methoden, aus denen die globale Referenz eimer erreichbar ist }
Übung 2.17: Untersuchen und testen Sie die folgende Klasse LokaleReferenz. Wie viele Eimer erscheinen bei der Ausführung im Fenster? Erklären Sie, warum. Sie sollen auch alle Kommentare in der Klasse verstehen und nachvollziehen können. Warum werden in privateMethode die Ausnahmen nicht aufgefangen?
Verändern Sie das Programm so, dass Sie privateMethode zweimal aufrufen.
import lehrbuch.*; // (2.34) public class LokaleReferenz extends Programm { private void privateMethode() throws VollAusn, LeerAusn { Eimer eimer; // lokale Referenz ¬ eimer = new Eimer(); // ein Objekt eimer.anzeigen(); // Methodenaufruf für das erzeugte Objekt eimer.fuellen(); eimer.entleeren(); // e.fuellen(); // lokale Referenz e von hier nicht erreichbar } public void start() { try { privateMethode(); // Aufruf der privaten Methode // eimer.fuellen(); // lokale Referenz eimer von hier nicht erreichbar Eimer e; // eine andere lokale Referenz ¬ e = new Eimer(); // ein anderes Objekt e.anzeigen(); e.fuellen(); e.entleeren(); } catch (VollAusn ausnahme) { meldung("Eimer schon voll"); } catch (LeerAusn ausnahme) { meldung("Eimer noch leer"); } } }
© APSIS GmbH |