studyklar
GdI 2 · Übungsblatt 8 · Aufgabe 4

Schiff ohne Kapitän: Absturz, abfangen, verbieten

Ein Schiff hat einen Kapitän. Was passiert, wenn man stattdessen null übergibt, also gar kein Objekt? Erst stürzt das Programm ab, dann fangen wir den Fehler ab, zuletzt verbieten wir so ein Schiff ganz. Rechts stehen die Klassen des aktuellen Teils, die Zeilen zum Schritt sind hervorgehoben. Mit Weiter geht es Schritt für Schritt voran.

Die Aufgabe

Aufgabe 4

a) Programmieren Sie eine Klasse „Kapitaen“ mit den String-Attributen vorname und nachname und dem kanonischen Konstruktor, der beide Attribute mit Werten versieht. Zudem soll die Methode getNachname( ) erstellt werden.

Programmieren Sie eine zweite Klasse Schiff mit dem Attribut name und einem weiteren Attribut kapitaen, dem ein Kapitaen-Objekt zugewiesen werden soll. Auch diese Klasse soll einen kanonischen Konstruktor besitzen. Weiterhin soll eine toString-Methode hinzugefügt werden, die einen String mit dem Namen des Schiffs und dem Nachnamen des Kapitäns zurückgibt (und hierfür die Methode „getNachname“ aufruft.).

Legen Sie nun in der main-Methode einer weiteren Klasse einen Kapitaen und ein Schiff mit Namen und Kapitaen an und erzeugen Sie eine Ausgabe auf der Konsole.

Erzeugen Sie in der main-Methode ein zweites Schiff-Objekt. Übergeben Sie dem Konstruktor den Wert null anstelle eines Kapitaen-Objekts. Erzeugen Sie ebenfalls eine Ausgabe auf der Konsole und schauen Sie, was passiert.

b) Behandeln Sie nun die Exception in der toString-Methode von „Schiff“. Der Benutzer soll beim Auftreten dieser Exception darüber informiert werden, dass kein Kapitaen angegeben ist, und es soll in diesem Fall nur der Name des Schiffs ausgegeben werden.

c) Nun soll verhindert werden, dass man überhaupt ein Schiff anlegen kann ohne ihm ein richtiges Kapitaen-Objekt zu übergeben. Hierzu soll der Konstruktor von Schiff eine IllegalArgumentException werfen. Ändern Sie den Konstruktor und testen Sie den geänderten Code.

Zwei Klassen: Kapitaen mit Vor- und Nachname, Schiff mit Name und Kapitän. toString von Schiff fragt den Kapitän nach seinem Nachnamen. Ohne Kapitän geht das schief. Die drei Teile zeigen drei Antworten darauf.

Zwei kleine Abweichungen von der Musterlösung: Die Ausgabe schreibt „Kapitän“ statt „Kapitaen“. In Teil c) prüft der Konstruktor den Kapitän vor den Zuweisungen; das Ergebnis ist dasselbe, weil bei null ohnehin kein Schiff entsteht.

Merke: Eine Methode auf null aufzurufen, löst eine NullPointerException aus. Besser als sie abzufangen ist oft, den ungültigen Wert gar nicht erst anzunehmen.
  1. a) Klassen schreiben, Schiff mit und ohne Kapitän ausgeben: Absturz.
  2. b) Die Ausnahme in toString abfangen und einen Hinweis ausgeben.
  3. c) Im Konstruktor ein Schiff ohne Kapitän verbieten.

Die Klasse Kapitaen

public class Kapitaen {     private String vorname;    private String nachname;     public Kapitaen(String vorname, String nachname) {        this.vorname = vorname;        this.nachname = nachname;    }     public String getNachname() {        return nachname;    }}

Zwei private-Attribute vom Typ String. Der kanonische Konstruktor ist der Konstruktor, der für jedes Attribut einen Parameter hat und alle Attribute damit füllt. getNachname() gibt den Nachnamen zurück; den Vornamen braucht die Aufgabe nicht.

Aus Blatt 5, Aufgabe 1 („Eine eigene Klasse Tier mit Konstruktor und toString“): Der Konstruktor füllt die Attribute beim new; this.nachname ist das Attribut, nachname allein der Parameter.

Die Klasse Schiff hat ein Kapitaen-Objekt als Attribut

public class Schiff {     private String name;    private Kapitaen kapitaen;     public Schiff(String name, Kapitaen kapitaen) {        this.name = name;        this.kapitaen = kapitaen;    }

Das Attribut kapitaen hat den Typ Kapitaen. Es enthält also einen Verweis auf ein Kapitaen-Objekt. Der kanonische Konstruktor bekommt den Namen und den Kapitän und speichert beide.

Der Konstruktor prüft nichts. Er nimmt auch null an, den Wert für „kein Objekt“. Genau das wird gleich zum Problem.

Aus Blatt 5, Aufgabe 3 („Studierende und Studiengänge: static-Zähler und Objekte in Attributen“): Ein Attribut kann ein Objekt einer anderen Klasse aufnehmen. Enthält es null, verweist es noch auf kein Objekt.
Noch 10 Schritte bis zum Ergebnis
Den ganzen Lösungsweg sehen Studierende und Lehrende der HS KL. Registriere dich mit deiner Adresse @stud.hs-kl.de oder @hs-kl.de, dann geht es hier direkt weiter.

Teil a)

Kapitaen, Schiff, SchiffApp

Abbildung 1Teil a)

Kapitaen, Schiff, SchiffApp

public class Kapitaen {     private String vorname;    private String nachname;     public Kapitaen(String vorname, String nachname) {        this.vorname = vorname;        this.nachname = nachname;    }     public String getNachname() {        return nachname;    }}
LegendeKapitaen.java

Abbildung 1Teil a)

Kapitaen, Schiff, SchiffApp

public class Schiff {     private String name;    private Kapitaen kapitaen;     public Schiff(String name, Kapitaen kapitaen) {        this.name = name;        this.kapitaen = kapitaen;    }     @Override    public String toString() {        return "Name: " + name + ", Kapitän: " + kapitaen.getNachname();    }}
LegendeSchiff.java

Abbildung 1Teil a)

Kapitaen, Schiff, SchiffApp

public class SchiffApp {     public static void main(String[] args) {        Kapitaen julia = new Kapitaen("Julia", "Meyer");        Schiff schiff1 = new Schiff("MS Zweibrücken", julia);        System.out.println(schiff1);         System.out.println();         Schiff schiff2 = new Schiff("MS Pirmasens", null);        System.out.println(schiff2);    }}
LegendeSchiffApp.java, darüber die beiden Klassen.