© APSIS GmbH |
Seite 195
Seite 195
class Verbund { // (9.1) Element1 element1 = new Element1(); Element2 element2 = new Element2(); ... // usw. entsprechend der Anzahl der Elemente ElementN elementN = new ElementN(); }
Verbund objekt1 = new Verbund(), objekt2 = new Verbund(); objekt1.element1.methode(); // methode der Klasse Element1 wird für das Objekt objekt1.element1 aufgerufen objekt2.element1.methode(); // methode der Klasse Element1 wird für das Objekt objekt2.element1 aufgerufen objekt2.element2.methode(); // (eine andere) methode der Klasse Element2 wird für objekt2.element1 aufgerufen
objekt1.getElement1().methode(); // getter objekt1.setElement1(wert); // setter
public class Kunde { // (9.2) public String name; public int bonitaet; ... } ... Kunde kunde = new Kunde(); kunde.name = new String("Solymosi"); // Direktzugriff kunde.bonitaet = 100000;
Seite 196
Seite 196
Element[] reihung; // (9.3)
char[] zeile;
zeile = new char[80]; Eimer[] zweiEimer = new Eimer[2];
zweiEimer[1] = new Eimer(); zweiEimer[2] = new Eimer(); public void linksFuellen() throws VollAusn { zweiEimer[1].fuellen(); } public void rechtsFuellen() throws VollAusn { zweiEimer[2].fuellen(); }
Element[] referenz = new Element[LAENGE];
final int LAENGE = 20;
public void Reihung(int laenge) { reihung = new Element(laenge); }
Übung 9.1: Entwickeln Sie ein der Übung 6.8 auf Seite 133 ähnliches Programm für neun Kreise mit einer Reihung. An Stelle einer Referenz auf den vorgewählten Kreis können sie einen int-Wert mit der Nummer eines der neun Kreise einlesen. Dieser Index der Reihung "zeigt" auf den ausgewählten Kreis ähnlich wie eine Referenz. Sie können anschließend die gewünschte Aktion ("Bemalen", usw.) auswählen. Achten Sie jedoch darauf, dass die Kreise in derselben Reihenfolge angezeigt werden, wie die Operation zeichnen für sie aufgerufen wurde. Damit diese Ihrer Nummerierung entspricht, ist es zweckmäßig, vor dem Aufruf des Menüs alle neun Kreise zu zeichnen und anschließend zu verstecken; dann behalten sie ihre Positionen im Fenster während des gesamten Programmlaufs.
Seite 197
Element[] reihung = new Element[LAENGE]; int index = reihung.length 1; // ¬ reihung[index] = wert; // das letzte Element der Reihung
try { reihung[reihung.length] = wert; // falscher Zugriff ¬ } catch (IndexOutOfBoundsException ausnahme) { ...
class Reihungserweiterung extends Element[] { ... // in Java nicht erlaubt
boolean[] logReihung = { true, false, false, true, true };
Eimer[] zweiEimer = { new Eimer(), new Eimer() };
Seite 198
String zeichenkette = "Zeichenkette"; // Literal repräsentiert konstantes String-Objekt ¬ int laenge = zeichenkette.length(); // Informator, liefert Anzahl der Zeichen char zeichen = zeichenkette.charAt(laenge-1); // Informator, liefert ein Zeichen int pos = zeichenkette.indexOf('e'); // Informator, Index des ersten Vorkommnisses
zeichenkette = "Zweite " + zeichenkette; zeichenkette += " verlängert"; // Inhalt: "Zweite Zeichenkette verlängert"
zeichenkette = "" + eimer; // Abkürzung für eimer.toString()
zeichenkette = "<" + 0.5 + '>'; // Inhalt ist "<0.5>"
boolean b = true; String s = String.valueOf(b); // Inhalt ist "true" s = "" + b; // gleichwertig
Boolean b = new Boolean(zeichenkette); b = Boolean.valueOf(zeichenkette); ... // für die nummerischen Hüllenklassen Integer, Long, Float und Double ähnlich int ganzzahl = Integer.parseInt(zeichenkette); long lang = Long.parseLong(zeichenkette);
StringBuffer puffer = new StringBuffer(); // Konstruktor char zeichen = (char)System.in.read(); // ein Zeichen von der Konsole lesen puffer.append(zeichen); // neues Zeichen am Ende des Puffers hinzufügen ... puffer.setCharAt(pos, zeichen); // ändert das Zeichen mit der gegebenen Position
Seite 199
Kapitel 3.4.4. auf Seite 74
public static void main(String[] args);
public class Kommandozeilenparameter { // (9.4) public static void main(String[] args) { System.out.println(args[0]); // ¬ } }
java Kommandozeilenparameter
java Kommandozeilenparameter Hallo
Hallo
public class Addieren { // (9.5) public static void main(String[] args) { int a = new Integer(args[0]).intValue(); // ¬ int b = new Integer(args[1]).intValue(); // ¬ int c = a + b System.out.println(a + " + " + b + " = " + c); } }
Seite 200
import java.awt.Color; // (9.6) class Farbe extends lehrbuch.Aufz { public static final Farbe GRUEN = new Farbe(); public static final Farbe LILA = new Farbe(); ... // usw. } public class Farbuebersetzer { private static final Color[] rgb = { Color.green, Color.magenta, ... }; // in der Reihenfolge, wie die deutschen Farbnamen in Farbe vereinbart wurden public static Color farbuebersetzer (final Farbe farbe) { return rgb [farbe.pos()]; // ¬ } }
getGraphics().setColor(Farbuebersetzer.farbuebersetzer(Farbe.LILA));
Übung 9.2: Schreiben Sie ein Java-Applet, in dem ähnlich wie im Programm (3.20) auf Seite 74 eine Schriftzeile ausgegeben wird, deren Farbe aber zuvor von einer Auswahlliste ausgewählt wird.
Seite 201
Element[][] tabelle = new Element[BREITE][HOEHE]; // (9.7)
int[][] matrix = { {2, -6, 3}, {12, 0, 6}, {1, -1, 1}, };
Seite 201
public class StapelPol implements lehrbuch.kapitel8.Stapel { // (9.8) // polymorphe Implementierung von Stapel private Object[] inhalt; // ¬ private int spitze; public StapelPol(int groesse) { inhalt = new Object[groesse]; entleeren(); }
public void entleeren() { // ensures leer(); spitze = -1; }
public void eintragen(final Object element) throws VollAusn { try { spitze ++; // nächster freier Platz inhalt[spitze] = element; // ¬ // throws IndexOutOfBoundsException, wenn spitze = inhalt.length } catch (IndexOutOfBoundsException ausnahme) { spitze --; // zurücksetzen throw new VollAusn(); } }
public Object lesen() throws LeerAusn { // requires !leer() try { return inhalt[spitze]; // letztes eingetragenes Element ¬ // throws IndexOutOfBoundsException, wenn spitze = -1 } catch (IndexOutOfBoundsException ausnahme) { throw new LeerAusn(); } }
public void entfernen() throws LeerAusn { try { attrappe = inhalt[spitze]; // throws IndexOutOfBoundsException, wenn spitze = -1 spitze --; // Platz des letzten eingetragenen Elements freigeben } catch (IndexOutOfBoundsException ausnahme) { throw new LeerAusn(); } }
private static Object attrappe; // global, damit der Compiler es nicht wegoptimiert public boolean leer() { // const return spitze == -1; } public boolean voll() { // const return spitze == inhalt.length-1; } }
Übung 9.3: Implementieren Sie die Schnittstelle Warteschlange aus dem Programm (8.17) auf Seite 183 als Reihung (mit integriertem Stapeltestprogramm als main in der Klasse). Um die Ausnahmefälle ohne if erkennen (s. Kapitel 10.1.5. auf Seite 219) zu können, lösen Sie die Ausnahme IndexOutOfBoundsException mit einer Attrappe:
private static Object attrappe; // global, damit der Compiler es nicht wegoptimiert attrappe = inhalt[anzahl]; // throws IndexOutOfBoundsException bei anzahl == inhalt.length attrappe = inhalt[anzahl-1]; // throws IndexOutOfBoundsException bei anzahl == 0
Im Stapel haben wir einen Index spitze geführt. In der Warteschlange müssen Sie zwei Indizes aeltestes und juengstes führen. Wenn ein Index das Ende der Reihung erreicht (überläuft) soll er bei 0 wieder angesetzt werden. Am einfachsten ist dies mit dem Restoperator % zu berechnen:
juengstes = (juengstes + 1) % inhalt.length; // beim Überlauf wird 0
Abb. 9.1: Datenstruktur der Warteschlange
Seite 203
Seite 203
Abb. 9.2: Knoten
class Knoten { // (9.9) Object wert; // statt Object beliebige Klasse oder Datentyp (z.B. char) möglich Knoten verbindung; // Rekursion ¬ Knoten(final Object w) { // w like wert; Konstruktor mit einem Parameter wert = w; // verbindung == null }
Knoten(final Object w, final Knoten v) { // w like wert wert = w; verbindung = v; } }
Knoten knoten = new Knoten(Farbe.ROT), andererKnoten = new Knoten(new Eimer()); knoten.wert = Farbe.GRUEN; andererKnoten.wert = knoten.wert;
Seite 204
Knoten anker = null; // verkettete Liste erreicht über den Verweis auf das letzte Element // Anfügen eines neuen Knotens: anker = new Knoten(Farbe.BLAU, anker); // neuer Knoten; der Alte wird verkettet ¬ ... anker = anker.verbindung; // löschen des letzten Knotens der Liste
Abb. 9.3: Rückwärts verkettete Liste
Seite 204
package lehrbuch.kapitel8; // (9.10) public class StapelListe implements Stapel { // Listenimplementierung von Stapel private class Knoten { ... // innere Klasse wie im Programm (9.9) } private Knoten anker; // ¬
public StapelListe() { anker = null; }
public void eintragen (final Object element) throws VollAusn { try { anker = new Knoten(element, anker); } // new throws OutOfMemoryError catch (OutOfMemoryError ausnahme) { throw new VollAusn(); } } public Object lesen () throws LeerAusn { try { return anker.wert; } // . throws NullPointerException catch (NullPointerException ausnahme) { throw new LeerAusn(); } } public void entfernen() throws LeerAusn { try { anker = anker.verbindung; } // . throws NullPointerException catch (NullPointerException ausnahme) { throw new LeerAusn(); } }
public void entleeren() { anker = null; } public boolean leer(){ return anker == null; } public boolean voll() { try { Knoten knoten = new Knoten(); // Versuch return false; // ist gelungen } catch (OutOfMemoryError ausnahme) { return true; // kein Platz mehr } } }
Übung 9.4: Testen Sie die obige Klasse mit Ihrem Programm aus der Übung 8.12 auf Seite 187. Wegen der unveränderten Spezifikation dürften Sie keine Veränderung des Programmverhaltens wahrnehmen.
Seite 205
public void kopieren(final StapelListe quelle) throws VollAusn { // (9.11) anker = knotenKopie(quelle.anker); } private Knoten knotenKopie(final Knoten qu) throws VollAusn { try { Knoten ziel = new Knoten(qu.wert); // throws NullPointerException bei qu == null ziel.verbindung = knotenKopie(qu.verbindung); // rekursiver Aufruf ¬ return ziel; } catch (NullPointerException ausnahme) { return null; } // Liste zu Ende catch (OutOfMemoryError ausnahme) { // kein Speicher mehr frei throw new VollAusn(); } }
public boolean gleich(final StapelListe stapel) { // const return knotenVergleich(anker, stapel.anker); } private boolean knotenVergleich(final Knoten erster, final Knoten zweiter) { try { return erster.wert == zweiter.wert & // throws NullPointerException, wenn eine Referenz == null knotenVergleich(erster.verbindung, zweiter.verbindung); // ¬ } catch (NullPointerException ausnahme) { // eine der Listen zu Ende return erster == null & zweiter == null; // ob auch die andere? } }
Abb. 9.4: Rekursive Abarbeitung
b.kopieren(a);
Abb. 9.5: Stapel bei Rekursion
Übung 9.5: Implementieren Sie die Kopieroperation und den Vergleich des Stapels mit der Reihungsimplementierung aus dem Programm (9.8) auf Seite 201 mit der Technik der rekursiven Abarbeitung.
Übung 9.6: Erstellen Sie einen Ganzzahlstapel als Reihung und erweitern Sie ihn so, dass er auch eine Funktion exportiert, die die Summe aller gestapelten Zahlen liefert. Implementieren Sie diese Operation rekursiv.
Seite 209
class WarteschlangeListe implements Warteschlange { // (9.12) // (polymorphe) Listenimplementierung von Warteschlange private class Knoten { ... // innere Klasse wie im Programm (9.9) private Knoten aelteste, juengste; public WarteschlangeListe() { aelteste = null; juengste = null; } ...
Abb. 9.6: Vorwärts verkettete Liste
public void entleeren() { aelteste = null; } public Object lesen () throws LeerAusn { try { return aelteste.wert; } catch (NullPointerException ausnahme) { throw new LeerAusn(); } } public void entfernen() throws LeerAusn { try { aelteste = aelteste.verbindung; } catch (NullPointerException ausnahme) { throw new LeerAusn(); } } public boolean leer(){ return aelteste == null; } public boolean voll() { try { Knoten knoten = new Knoten(); // new throws OutOfMemoryError return false; // ist gelungen } catch (OutOfMemoryError ausnahme) { return true; // kein Platz mehr } }
private Knoten neu; // global für den Ausnahmebehandlungsteil public void eintragen (final Object element) throws VollAusn { try { neu = aelteste.verbindung; // throws NullPointerException im Sonderfall, wenn Warteschlange noch leer ¬ neu = new Knoten(element, aelteste); // throws OutOfMemoryError neu.verbindung = null; // zurücksetzen juengste.verbindung = neu; // neuer jüngster Knoten wird eingefügt } catch (OutOfMemoryError ausnahme) { throw new VollAusn(); } catch (NullPointerException ausnahme) { // Sonderfall: Warteschlange leer juengste = neu; aelteste = neu; } }
Übung 9.7: Implementieren Sie die Kopieroperation und den Vergleich der Listenimplementierung der Warteschlange mit der Technik der rekursiven Abarbeitung.
Übung 9.8: Eine Warteschlange kann auch mit einem Anker als ein vorwärts verketteter Ring implementiert werden. Der Anker referiert den jüngsten Knoten; dessen Verkettung referiert den ältesten Knoten. Implementieren Sie nun die Warteschlange auf diese Weise.
Seite 211
class Knoten { Object wert; Knoten vorwaerts, rueckwaerts; // Vor- und Rückwärtsverkettung ¬ }
Abb. 9.7: Doppelt verkettete Liste
public class PosListePol implements PosListe { // (9.13) // positionierbare Liste, polymorphe Implementierung private class Knoten { Object wert; Knoten vorwaerts, rueckwaerts; // Vor- und Rückwärtsverkettung Knoten(Object wert, Knoten vorwaerts, Knoten rueckwaerts) { this.wert = wert; this.vorwaerts = vorwaerts; this.rueckwaerts = rueckwaerts; } } private Knoten anfang, ende, aktuell; // ¬
public PosListePol() { entleeren(); } public void entleeren() { // macht die Liste leer anfang = null; ende = null; aktuell = null; }
public void eintragen(final Object element) throws VollAusn { // trägt element hinter die aktuelle Position ein try { ... // hier nur der allgemeine Fall mitten in der Kette: Knoten neu = new Knoten(element, aktuell.vorwaerts, aktuell); // neuer Knoten zeigt vorwärts auf den aktuellen, rückwärts auf den dahinter aktuell.vorwaerts.rueckwaerts = neu; // nach dem aktuellen einfügen aktuell.vorwaerts = neu; aktuell = neu; } catch (OutOfMemoryError ausnahme) { throw new VollAusn(); } } public void erstesEintragen(final Object Element) { ... // ähnlich
public void loeschen() throws LeerAusn { try { ... // hier nur der allgemeine Fall mitten in der Kette: Knoten hinten = aktuell.rueckwaerts; // throws NullPointerException, wenn Liste leer: aktuell = null Knoten vorne = aktuell.vorwaerts; // throws NullPointerException, wenn Liste leer hinten.vorwaerts = vorne; vorne.rueckwaerts = hinten; aktuell = hinten; } catch (NullPointerException ausnahme) { throw new LeerAusn(); } } public Object aktuellesElement() throws LeerAusn { try { return aktuell.wert; // throws NullPointerException } catch (NullPointerException ausnahme) { throw new LeerAusn(); } }
public void vorwaerts() throws LeerAusn { try { aktuell = aktuell.vorwaerts; } catch (NullPointerException ausnahme) { throw new LeerAusn(); } } public void rueckwaerts() throws LeerAusn { ... // ähnlich public void anfang() { aktuell = anfang; } public void ende() { ... // ähnlich public boolean leer(){ return anfang == null; } ... // weitere Methoden }
Übung 9.9: Programmieren Sie die Methoden kopieren, gleich und suchen der positionierbaren Liste mit Hilfe der Ausprägung des iterators.
Seite 212
Abb. 9.8: Binärbaum
public class Binaerbaum { // (9.14) protected class Knoten { private Object wert; private Knoten links, rechts; public Knoten (Object wert, Knoten links, Knoten rechts) { this.wert = wert; this.links = links; this.rechts = rechts; } } protected Knoten wurzel; ... // Zugriffsmethoden }
Übung 9.10: Erweitern Sie die Klasse Binaerbaum mit Navigationsoperationen.
Seite 213
Abb. 9.9: Aufzählungsobjekte
private class Knoten { // geschachtelte Klasse innerhalb von Aufz // (9.15) int pos; Knoten naechster, vorheriger, erster, letzter; // Komponenten für die Verkettung String name; // Name des Wertobjekts } private Knoten knoten; private static Aufz ersterAkt, letzterAkt; // Randknoten für den aktuellen Typ private static Bool neuerTyp; protected Aufz() { // geschützter Konstruktor, nur für die Erzeugung eines neuen Werts try { knoten = new Knoten(); neuerTyp = new Bool(letzterAkt == null || ! getClass().isInstance(letzterAkt)); neuerTyp = neuerTyp.naechster(); // Ausnahme beim ersten Knoten provozieren // neuer Aufzählungswert für denselben Typ, verketten: knoten.pos = letzterAkt.knoten.pos + 1; // durchnummerieren knoten.vorheriger = letzterAkt; letzterAkt.knoten.naechster = this; } catch (BereichAusn ausnahme) { // mit dem ersten Knoten eines Aufzählungstyps wird eine neue Kette begonnen knoten.pos = 0; ersterAkt = this; } letzterAkt = this; // neuer letzter Wert für den aktuellen Typ knoten.erster = ersterAkt; // setzen Komponente letzter auf letzterAkt in allen Knoten des aktuellen Typs: setzen(knoten); // s. Programm (13.8) // setzen Komponente name mit dem Namen des aktuellen Werts: knoten.name = namenErmitteln(); // s. Programm (13.8) }
public static final Farbe GRUEN = new Farbe();
Seite 214
public class SeqDateiVektor implements SeqDatei { // hier ohne Ausnahmen // (9.16) private java.util.Vector inhalt = new java.util.Vector(); // ¬ public void neuBeschreiben() { inhalt.removeAllElements(); // ¬ } public void zuruecksetzen() { index = 0; } private int index = 0; public void eintragen(final Object element) { inhalt.addElement(element); // wird ans Ende angehängt ¬ } public void naechstesElement() { index ++; } public Object aktuellesElement() throws DateiendeAusn { try { return inhalt.elementAt(index); // throws ArrayIndexOutOfBoundsException ¬ } catch (ArrayIndexOutOfBoundsException ausnahme) { throw new DateiendeAusn(); } } public boolean endeDerDatei() { return index == inhalt.size(); } }
Übung 9.11: Implementieren Sie die Schnittstelle Warteschlange mit Hilfe einer dynamischen Reihung.
© APSIS GmbH |