X) 05 Ein Kommen und Gehen

Sehen wir uns noch mal das letzte Kapitel an. Dort haben wir Methoden in unserer Wirtschaft angelegt, durch die ein Gast das Gasthaus betreten und verlassen kann. Falls dies schief läuft (Gast ist nicht in der Wirtschaft, Wirtschaft voll), wird in unserer Klasse Wirtschaft eine Meldung ausgegeben (wenn überhaupt) und sonst nichts. Dadurch nehmen wir der aufrufenden Methode die Möglichkeit auf solche Ereignisse zu reagieren. Dies wollen wir in diesem Kapitel ändern.

Sie haben es bereits erraten! Dieses Kapitel dreht sich um Fehlerbehandlung. Sehen wir uns zuerst die Situation an, wenn die Wirtschaft voll ist.

public void betreten(Gast g) {

  for (int i = 0; i < this.plaetze.length; i++) {
    if (this.plaetze&#91;i&#93; == null) {
      System.out.println("Willkommen " + g);
      this.plaetze&#91;i&#93; = g;
      return;
    }
  }
  System.out.println("Kein Platz mehr frei");
}&#91;/sourcecode&#93;

Natürlich ist ein <code>System.out.println</code> keine akzeptable Rückmeldung! Anstelle dieser Ausgabe könnten wir eine <strong>Fehlermeldung</strong> werfen. Aber ist das in diesem Fall wirklich sinnvoll? Ist es wirklich eine Ausnahme bzw. ein Problem und so ungewöhnlich, dass eine Wirtschaft voll besetzt ist? <strong>Nein</strong>, ist es nicht! Deshalb ist es an dieser Stelle weitaus sinnvoller lediglich den Rückgabewert der Methode so zu verändern, dass ein <code>boolean</code> zurückgegeben wird. Ist der Rückgabewert <code>true</code>, hat sich der <code>Gast</code> erfolgreich an einen Platz gesetzt. Ist er <code>false</code>, ist leider kein Platz mehr frei. Modifizieren wir den Code dieser Methode also wie folgt:

public boolean betreten(Gast g) {

  for (int i = 0; i < this.plaetze.length; i++) {
    if (this.plaetze&#91;i&#93; == null) {
      System.out.println("Willkommen " + g);
      this.plaetze&#91;i&#93; = g;
      return true;
    }
  }
  return false;
}&#91;/sourcecode&#93;

Da wir nun keine Ausgabe mehr in unserem Programm haben, wenn ein Gast keinen Platz mehr findet, müssen wir die aufrufende Methode in der Klasse <code>Welt</code> noch modifizieren. Wir prüfen hierbei den Rückgabewert von <code>betreten</code> und geben im Falle einer vollen <code>Wirtschaft</code> einen entsprechenden Text aus.

private static void gastKommt(Gast g) {

  if (g.isDurstig() || g.isHungrig()) {
    if (!Welt.zumJavaBlogBuch.betreten(g)) {
      System.out.println(g + " findet leider keinen Platz mehr");
    }
  }
  else {
    System.out.println(g + " hat keinen Hunger und auch keinen Durst");
  }
}

Als nächsten Schritt sollten wir die Routine überarbeiten, wenn ein Gast die Wirtschaft wieder verlässt. Die Implementierung sieht momentan so aus:

public void verlassen(Gast g) {

  for (int i = 0; i < this.plaetze.length; i++) {
    if (this.plaetze&#91;i&#93; == g) {
      System.out.println("Auf Wiedersehen " + g);
      this.plaetze&#91;i&#93; = null;
      return;
    }
  }
}&#91;/sourcecode&#93;

Natürlich ist es in diesem kleinen Beispiel nicht zwingend nötig darauf zu reagieren, wenn ein Gast nicht in der Wirtschaft ist. Zu einem späteren Zeitpunkt könnte dieses Wissen aber mehr Wert werden. Doch wie sollten wir in diesem Fall reagieren? Auch mit einem anderen Rückgabewert, oder doch mit einer <code>Exception</code>? Vergleichen wir die beiden Fälle. Es ist völlig normal und auch ohne Probleme möglich, dass ein Gast eine Wirtschaft betreten möchte, und dabei feststellt, dass kein Platz mehr frei ist. Es ist allerdings alles andere als normal und auch nicht möglich, dass ein Gast ein Gasthaus verlässt, in welchem er sich gar nicht befindet. Es handelt sich also um einen <strong>Fehler</strong> bzw. um eine <strong>Ausnahme</strong>.

Zur Reaktion auf diese Gegebenheit sollten wir also eine <code>Exception</code> werfen. Hierzu müssen wir uns zuerst einmal eine entsprechende anlegen (es ist höchst unwahrscheinlich, dass es in Java eine Standard-Exception für dieses Verhalten gibt). 

Diese Fehlermeldung sollte einen Text enthalten, um den Fehler näher zu beschreiben. Ansonsten sind keine Eigenschaften notwendig. Es genügt also eine Klasse, die von <code>Exception</code> erbt, und den Konstruktor mit dem Übergabeparameter einer Nachricht der Elternklasse aufruft.

package de.jbb.ausnahmen;

public class GastNichtAnwesend extends Exception {

  public GastNichtAnwesend(String arg0) {
    super(arg0);
  }
}

Nun müssen wir den Methodenkopf unserer verlassen-Methode so erweitern, dass von dieser Methode die eben programmierte Fehlermeldung geworfen werden kann.

public void verlassen(Gast g) throws GastNichtAnwesend {

Natürlich dürfen Sie auch nicht vergessen, diesen Fehler dann ggf. auch über throws zu werfen. Nach den Veränderungen sieht unsere Methode nun so aus:

public void verlassen(Gast g) throws GastNichtAnwesend {

  for (int i = 0; i < this.plaetze.length; i++) {
    if (this.plaetze&#91;i&#93; == g) {
      System.out.println("Auf Wiedersehen " + g);
      this.plaetze&#91;i&#93; = null;
      return;
    }
  }
  throw new GastNichtAnwesend(g + " befindet sich nicht im Gasthaus");
}&#91;/sourcecode&#93;

Als letzten Schritt müssen wir die Fehlermeldung in unserer <code>Welt</code>-Klasse mit einem <strong>try-catch-Block</strong> abfangen. Tritt eine solche Fehlermeldung auf, wird der Fehler ausgegeben. Hierzu verwenden wir den <strong>Error-Stream</strong>, welchen wir mittels <code>System.err.println</code> anstelle von <code>System.out.println</code> einsetzen. Dadurch können wir (oder ein Logging-Tool) unterscheiden, ob es sich um eine normale Systemausgabe oder eine Fehlermeldung handelt.

private static void gastGeht(Gast g) {

  try {
    Welt.zumJavaBlogBuch.verlassen(g);
  }
  catch (GastNichtAnwesend gna) {
    System.err.println("Problem beim Verlassen:");
    System.err.println(gna.getMessage());
  }
}

3 Replies to “X) 05 Ein Kommen und Gehen”

  1. Faen

    Guten Tag alle miteinander,
    ich wollte mal fragen, ob ein neues Kapiel für „Wir bauen eine Wirtschaft“ bereits in Planung ist. Ich finde diese – ich nenns mal spielerisch – Aufarbeitung von Grundwissen sehr interessant 🙂
    lg

  2. Stefan Kiesel

    Hallo Faen,

    danke für das Lob! Ein solches Kapitel verlangt eine sehr genaue und zeitintensive Planung. Leider sind alle Autoren zur Zeit beruflich und/oder privat sehr stark gefordert (was auch der Grund dafür ist, dass die Anzahl der wöchentlich neuen Kapitel momentan reduziert werden musste), so dass bis jetzt niemand aus dem Java-Blog-Buch-Team in der Lage war, die notwendige Zeit aufzubringen.

    Aber mit diesem Kapitel im Hinterkopf, werde ich versuchen, demnächst die notwendige Zeit zu investieren. Gleichzeitig möchte ich an dieser Stelle auch noch einmal darauf hinweisen, dass wir noch Autoren suchen.

    Grüße
    Stefan

  3. NoName

    Hallo,
    und ein Lob an die Macher für dieses mal etwas andere Tutorial.
    Als alter software / java Hase muss ich hier allerdings anmerken: Einem Anfänger so früh beizubringen, wie er eigene Exception’s ableitet (oder viel mehr ihm zu zeigen, wie einfach das ist) ver-/ führt schnell zum Exceptions bauen. Ist vielleicht etwas zu sehr Geschmacksfrage, aber

    1) nicht für alles mögliche checked Exceptions werfen, sondern NUR für die Fälle, in denen man auch darauf reagieren möchte & kann,
    2) nicht für jede mögliche Fehlerbedingung eine eigene Exception Klasse

    Habe ich (v.a. in letzter Zeit) leider zu oft gesehen…

Schreibe einen Kommentar

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.