Jetzt anmelden...

Login
Passwort
Registrieren
02.01.21 2140 Views Kommentare [0] 1 0

credit: ©Ivan Kurmyshov

Java Tutorial #40

Eigene Exceptions erstellen

Die Java API stellt bereits ein stabiles Arsenal an Exceptions zur Verfügung. In den meisten Fällen dürften die auch ausreichen. Falls nicht, dann basteln wir uns einfach selbst welche. Wie das geht, erfahren Sie hier!

Falconbyte unterstüzen

Betrieb und Pflege von Falconbyte brauchen viel Zeit und Geld. Um dir auch weiterhin hochwertigen Content anbieten zu können, kannst du uns sehr gerne mit einem kleinen "Trinkgeld" unterstützen.

Schnelles Code-Beispiel

// Benutzerdefinierte Exception-Klasse
public class MeineException extends Exception { }

// Auslösende Methode
public void methodeX() throws MeineException{
    throw new MeineException();
}

    Inhaltsverzeichnis

  1. Eigene Exception-Klasse definieren
  2. Ein praktisches Beispiel
  3. Übungen

Eigene Exception-Klasse definieren

Klasse Exception erweitern

Eine eigene Exception-Klasse zu definieren, ist nicht schwierig. Es genügt zunächst, die Klasse Exception zu erweitern:

public class MeineException extends Exception{ }

Ein Objekt dieser benutzerdefinierten Exception-Klasse soll ausgelöst werden können.

Innerhalb unserer Exception-Klasse können wir natürlich auch eigene Methoden schreiben, die über die auf das Exception-Objekt verweisende Referenz e im catch-Block ausgeführt werden könnten.

Wir begnügen uns in diesem Fall mit dem Überschreiben der getMessage()-Methode:

public class MeineException extends Exception {
    @Override
    public String getMessage(){
        return "Ich wurde ausgelöst!";
    }
}

Eigene Exception auslösen

Um eine Exception selbst auszulösen, benötigen wir eine entsprechende Methode, welche die Exception werfen kann und innerhalb dieser den auslösenden Mechanismus mit dem Schlüsselwort throw und dem new-Operator für die Erzeugung eines neuen MeineException-Objekts:

Java eigene benutzerdefinierte auslösen

Da wir die Klasse Exception erweitern, gehört unsere benutzerdefinierten Exception hier zur Gruppe der checked Exceptions und muss mit einem try-catch-Block umschlossen werden - das Exception Handling wird vom Compiler also vorgeschrieben:

public class Rocket {

    public void methodeX() throws MeineException{
        if((int)(Math.random() * 3) == 0){
            throw new MeineException(); // wird zu 33% ausgelöst
        }
    }

    public static void main(String[] args) {

        Rocket r = new Rocket();
        try {
            r.methodeX(); // riskante Methode aufrufen
        } catch (MeineException e) {
            e.getMessage(); // Ich wurde ausgelöst!
        }
    }

}

Natürlich hätten wir auch RuntimeException oder eine Unterklasse davon erweitern können. Das Exception Handling wäre bei diesen unchecked Exceptions dann nicht vorgeschrieben.

Ein praktisches Beispiel

Verdeutlichen wir den Einsatz einer benutzerdefinierten Exception mit einer primitiven Raketenstart-Simulation.

Ob eine Rakete ihre Triebwerke zünden und abheben kann, hängt von vielen Faktoren ab. Neben umfangreichen technischen Checks und dem Treibstoffvorrat muss auch die Wetterlage für einen Start perfekt sein.

Wenn nicht alles zusammenpasst, wird der Start der Rakete unvermindert abgebrochen.

Das Java-Programm, dass dieses Prüfszenario für einen Raketenstart objektorientiert abbildet, besteht aus den Klassen Rakete, Wetter sowie der benutzerdefinierten Exception RocketStartException, die ausgelöst wird, wenn der Start nicht durchgeführt werden kann. Schließlich gibt es noch eine Klasse Startplattform, die wir für die Main-Methode nutzen.

Hier zunächst die Klasse RocketStartException:

public class RocketStartException extends Exception {
   @Override
   public String getMessage(){
       return "Es gibt ein Problem - Rakete kann nicht starten!";
   }
}

Die benutzerdefinierte Exception-Klasse ist recht unspektakulär. Sie kann lediglich die Meldung zurückliefern, dass etwas schiefgelaufen ist. Mehr brauchen wir hier aber auch nicht. Eine sinnvolle Programmerweiterung könnte übrigens so aussehen, drei unterschiedliche Exception-Typen zu schreiben, die je nach Problemfall für sich ausgelöst werden könnten (z.B. TechnikException, TreibstoffException, WetterException)

Die Klasse Wetter soll mit einer statischen Methode perfektesWetter() einen booleschen Wert zurückliefern, der bedingt durch einen Zufallsgenerator zu 50% true ist. Damit soll die Unbeständigkeit des Wetters simuliert werden:

public abstract class Wetter {

    public static boolean perfektesWetter(){
        int status = (int) (Math.random() * 2); // 0 oder 1

        if(status == 0){
            return true;
        }
        else{
            return false;
        }
    }
}

Nun zur eigentlich interessanten Klasse: Der Rakete:

public class Rakete {

    private boolean technikOK;
    private boolean treibstoffVoll;

    public Rakete(boolean technikOK, boolean treibstoffVoll){
        this.technikOK = technikOK;
        this.treibstoffVoll = treibstoffVoll;
    }

    public void triebwerkeZuenden() throws RocketStartException {

        if(!technikOK || !treibstoffVoll || !Wetter.perfektesWetter()) {
            throw new RocketStartException();
        }

        // Alles OK - Rakete startet!
        System.out.println("Raketentriebwerke gestartet!");
        System.out.println("Auf geht's zum Mars!");
    }

}

Es kommt hier auf die Methode triebwerkeZuenden() an. Diese Methode kann unter Umständen eine Exception vom Typ RocketStartException werfen (das ist unsere benutzerdefinierte Exception).

Diese RocketStartException wird dann ausgelöst, wenn der technischeCheck der Rakete nicht erfolgreich war, der Raketentreibstoff nicht voll ist oder kein perfektes Wetter gegeben ist. Mit anderen Worten, wenn eine der drei Bedingungen false ist:

  • Die Instanzvariable technikOK einer Instanz von Rakete ist nicht true.
  • Die Instanzvariable technikOK einer Instanz von Rakete ist nicht true.
  • Der Rückgabewert der statischen Methode perfektesWetter() der Klasse Wetter ist nicht true

In solch einem Fall bricht die Methode tritt eine Ausnahmesituation ein und es wird die Exception RocketStartException geworfen. Dadurch bricht die Ausführung der Methode triebwerkeZuenden() ab und wird nicht zuende gebracht.

Sind hingegen die drei Bedingungen true wird die Methode vollständig ausgeführt und die Rakete kann abheben. Vereinfacht simuliert haben wir das mit zwei System.out.println()-Anweisungen.

Zur Objekterzeugung von Rakete und der Ausführung der triebwerkeZuenden()-Methode sowie dem dazugehörigen Exception-Handling verwenden wir die Klasse Startplattform.

public class Startplattform {

    public static void main(String[] args) {

        Rakete r = new Rakete(true, true);
        try {
            r.triebwerkeZuenden(); // riskante Methode
        } catch (RocketStartException e) {
            System.out.println(e.getMessage());
        }
        System.out.println("Programm ordnungsgemäß beendet");
    }
}

Egal was passiert: Durch das implementierte Exception Handling stürtzt das Programm nicht ab und kann nach der Methode triebwerkeZuenden() weiterlaufen.

Wäre es nicht phantastisch, auch außerhalb eines Java-Programms folgende Meldung zu lesen?

Raketentriebwerke gestartet!
Auf geht's zum Mars!

🚀

Übungen

einfach

Erstellen sie eine benutzerdefinierte Exception namens RuntimeMe, die RuntimeException erweitert.

Implementieren Sie nun eine Klasse namens Falcon9 mit einer Methode namens abheben(), die einen int-Parameter entgegennimmt. Diese Methode kann eine RuntimeMe-Exception auslösen, wenn der Parameter eine ungerade Zahl ist.

Testen Sie die Methode.

Lösung ein-/ausblenden

mittel

Lässt sich der folgende Code compilieren? Falls nein: Wo liegt der Fehler?

public class FalconHeavy {

    public static void engage(int y){

        String z;

        switch(y){
            case 0: z = "0"; break;
            case 1: z = "1"; break;
            case 2: z = "2"; break;
            default: throw new Exception();
        }

    }

}
Lösung ein-/ausblenden

schwer

Erstellen Sie eine Exception namens UngueltigeEingabe, die IllegalArgumentException erweitert.

Erstellen Sie nun eine Klasse namens Adresse mit zwei Instanzvariablen String strasse und int hausnummer, die über Parametervariablen im Konstruktor initialisiert werden sollen.

Allerdings (und jetzt wird es schwierig): Ein Objekt darf nur bei gültigen Parameter-Werten instanziiert werden. Gültig sind die Werte, wenn der String mindestens 3 Zeichen und der int-Wert größer als 0 ist. Die Prüfung erfolgt im Konstruktor.

Entsprechen die Parameter-Werte nicht den Vorgaben, wird die Exception UngueltigeEingabe ausgelöst.

Damit das Programm trotz möglicher Ausnahmesituation weiterläuft und nicht abstürzt, bauen Sie bitte an geeigneter Stelle das Exception Handling ein.

Lösung ein-/ausblenden

Falconbyte unterstützen

Kommentar schreiben

Alle Kommentare

Es gibt bislang noch keine Kommentare zu diesem Thema.

Objekte löschen

Wir wissen, wie wir Objekte erstellen können. Aber wie werden wir sie wieder los?

Einstieg Objektorientierung

Lernen Sie die Grundlagen der Objektorientierung

Arrays in Java

Arrays ermöglichen das Speichern von Daten in einer übergeordneten Datenstruktur

FALCONBYTE.NET

Handmade with 🖤️

© 2018-2021 Stefan E. Heller

Impressum | Datenschutz

Falconbyte GitHub facebook programmieren lernen twitter programmieren lernen discord programmieren lernen