Q1 OOP in Java

Telefonbuch-Spielwiese

Lösung geprüft

Die Aufgabe der heutigen Stunde ist die Telefonbuch-Spielwiese! Alle Klassen stehen, jetzt bauen wir endlich einen echten Kontakt zusammen und lassen ihn ausgeben. Das ist der Moment, in dem man merkt, ob das Zusammenspiel der sechs Klassen wirklich funktioniert.

Die Aufgabenstellung lautet

Schreibe eine Klasse Spielwiese und probiere und teste die Klasse Kontakt aus. Zum Beispiel könnte die Spielwiese die folgende Ausgabe auf der Konsole erzeugen.

Datei speichern: neue Zip-Datei Telefonbuch_nachname.zip mit Code und UML.

Zusatz: Bringen Sie ihre Ausgabe der Spielwiese durch passende Methoden in eine schönere Formatierung.

Lösungsprozess der Aufgabe

Spielwiese.java
/* meininfokurs.cmrg.site */
/**
 *
 * Spielwiese fuer das Telefonbuch
 *
 * @version 1.0 vom 14.09.2025
 * @meininfokurs.cmrg.site
 */

import java.time.LocalDate;
import java.time.LocalTime;

public class Spielwiese {

    public static void main(String[] args) {

        // Ein Kontakt, erstmal nur mit Namen
        Kontakt firma = new Kontakt("Muster GmbH");

        // Adresse, Telefon und E-Mail nachtragen
        firma.setAdresse(new Adresse("Hauptstr.", "1", "65183",
                                     "Wiesbaden", "DE",
                                     Adresse.Typ.GESCHAEFTLICH));

        firma.setTelefon(new Telefon("+49 611 123456", Telefon.Typ.FESTNETZ));

        firma.setEmail(new Email("info@muster.de", Email.Typ.GESCHAEFTLICH));

        // Zwei Termine: einer mit Uhrzeit, einer ohne
        firma.fuegeTerminHinzu(new Termin(LocalDate.of(2025, 9, 1),
                                          LocalTime.of(14, 30),
                                          Termin.Art.GESCHAEFTLICH));

        firma.fuegeTerminHinzu(new Termin(LocalDate.of(2025, 12, 24),
                                          Termin.Art.GEBURTSTAG));

        // Zwei Gruppen
        firma.fuegeGruppeHinzu(new Gruppe("Lieferanten"));
        firma.fuegeGruppeHinzu(new Gruppe("Newsletter"));

        // Ausgeben - ruft intern toString() auf
        System.out.println(firma);

    } // end of main

} // end of class Spielwiese

Und das kommt dabei raus

Konsole
=== Kontakt ===
Name    : Muster GmbH
Adresse{
strasse='Hauptstr.'
, hausnummer='1'
, plz='65183'
, ort='Wiesbaden'
, land='DE'
, typ='GESCHAEFTLICH'
'}

Telefon : Telefon{nummer='+49 611 123456', typ=FESTNETZ}
E-Mail  : Email{adresse='info@muster.de', typ=GESCHAEFTLICH}

=== Termine ===
Termin{datum=2025-09-01, uhrzeit=14:30, art=GESCHAEFTLICH}
Termin{datum=2025-12-24, uhrzeit=null, art=GEBURTSTAG}

=== Gruppen ===
Gruppe{name='Lieferanten'}
Gruppe{name='Newsletter'}

Ein einziges println für all das

Im ganzen main steht genau ein System.out.println(firma);. Alles andere passiert von selbst, weil toString() automatisch aufgerufen wird – und zwar kettenweise: die toString() von Kontakt hängt adresse an einen String, dadurch wird die toString() von Adresse aufgerufen, und so weiter durch alle sechs Klassen.

Das ist der Grund, warum wir in jeder Klasse eine toString() geschrieben haben. Hättest du eine vergessen, stünde an der Stelle Gruppe@6d06d69c statt Gruppe{name='Lieferanten'}. Damit findest du auch schnell die Klasse, in der sie fehlt.

uhrzeit=null ist kein Fehler

Beim zweiten Termin steht uhrzeit=null. Das ist genau so gewollt: der Geburtstag wurde über den Konstruktor ohne Uhrzeit angelegt, also gibt es keine. null heißt hier „bewusst nicht gesetzt".

Aufpassen musst du nur, wenn du damit weiterrechnest. firma.getTermine().get(1).getUhrzeit().getHour() würde eine NullPointerException werfen, weil man von null keine Stunde erfragen kann. Beim Ausgeben ist es harmlos – da macht Java daraus einfach den Text „null".

Warum erst der Konstruktor mit einem Argument

Der Kontakt wird mit new Kontakt("Muster GmbH") angelegt und alles Weitere danach über Setter nachgetragen. Das könnte man auch mit dem großen Konstruktor auf einmal machen – nur müsste man dafür die beiden Listen vorher selbst bauen und befüllen, und der Aufruf hätte sechs Argumente. So ist es lesbarer, und es entspricht auch dem, was die App macht: erst den Namen eintippen, dann Stück für Stück ergänzen.

Möglich ist das nur, weil der kleine Konstruktor die Listen anlegt. Ohne das würde der erste fuegeTerminHinzu sofort abstürzen.

Zur Zusatzaufgabe: schöner formatieren

Die Ausgabe der Adresse ist ehrlich gesagt nicht schön – die Kommas stehen am Zeilenanfang und am Ende hängt ein einsames '}. Das kommt daher, dass die toString() automatisch erzeugt und dann mit Zeilenumbrüchen versehen wurde.

Für die Zusatzaufgabe schreibt man eine eigene Methode daneben, statt toString() zu verbiegen:

// in der Klasse Adresse
public String formatiert() {
    return strasse + " " + hausnummer + "\n"
         + plz + " " + ort + " (" + land + ")" + "\n"
         + "Typ: " + typ;
}

Damit wird aus dem Klammergewirr:

Konsole
Hauptstr. 1
65183 Wiesbaden (DE)
Typ: GESCHAEFTLICH

Warum nicht einfach toString() umschreiben? Weil die beiden verschiedene Zwecke haben. toString() soll beim Debuggen zeigen, was wirklich im Objekt steht – mit allen Attributnamen, auch wenn es hässlich aussieht. formatiert() ist für den Benutzer. Beides in eine Methode zu stopfen geht meistens schief.

Die Abgabe ist eine Zip-Datei mit Code und UML – also alle .java- und alle .uml-Dateien zu Kontakt, Telefon, Email, Adresse, Termin, Gruppe und Spielwiese. Wer nur die Java-Dateien einpackt, hat die halbe Abgabe vergessen.

Aufgabe suchen

Tippe los. Strg+K öffnet die Suche von überall.

Zuletzt angesehen

Werbung