Java: NullPointerException zum Erkennen von Programmierfehlern

Werden einer public oder protected-Methode null-Parameter überreicht, die per Vorbedingung nicht null sein dürfen, werde ich zukünftig prinzipiell am Anfang der Methode eine NullPointerException werfen. Verzichte ich darauf, kann mein Programm nicht richtig arbeiten, ohne dass ich dies bemerke.

Ein aktuelles Beispiel aus meinem Projekt JPhotoTagger: Es können benutzerdefinierte Dateifilter angelegt werden. Der Datenbank-Primärschlüssel ist der Name des Filters. Dieser wird in ein JTextField eingegeben, und bevor der Filter in die Datenbank gespeichert wird, wird überprüft, ob der eingegebene Name bereits in der Datenbank existiert:

public boolean exists(String name) { ... }

Vermutlich sorgte die Autocomplete-Funktion des Editors dafür, dass nicht die Methode getText() des Textfelds aufgerufen wurde, sondern getName(). Diese liefert null (da ich das Textfeld nicht benannt habe). Das Ergebnis: exists() liefert immer false, denn das Tabellen-Namensfeld kann nicht auf NULL gesetzt werden.

Was den Fehler vorerst verbirgt: Beim Einfügen in die Datenbank wird die richtige Methode des Textfelds aufgerufen, es sieht alles gut aus, der Filter kann benutzt werden und auch modifiziert. Das Problem tritt erst später auf (oder nie), falls versucht wird, den gleichen Namen erneut per SQL-INSERT in die Datenbank zu schreiben. Hätte ich keine Einschränkung für den Namen gesetzt, gäbe es mehrere gleichnamige Filter in der Datenbank. Das Umstellen des Codes auf

public boolean exists(String name) {
    if (name == null) {
        throw new NullPointerException("name == null");
    }
    ....
}

zeigte den Fehler sofort.

assert ist kein Ersatz, dieses wird nur beim Entwickler ausgeführt, nicht beim Benutzer. Es kann auch nicht false geliefert werden, falls der Parameter null ist.

Zusammengefasst:

  • Explizit in den Javadoc-Kommentar der Methode schreiben, falls ein Methodenparameter null sein darf
  • Alle anderen Parameter dürfen per Vertrag – als Vorbedingung – nicht null sein, dies ist nicht zu dokumentieren
  • Die Vorbedingungen werden sichergestellt, bevor der Funktionscode ausgeführt wird. Ist ein Methodenparameter vertragswidrig null, werden in public und protected-Methoden NullPointerExceptions geworfen. Das gleiche gilt für ungültige Parameterwerte (IllegalArgumentException), falls die Methode in einem bestimmten Objekt-Zustand nicht aufgerufen werden darf (IllegalStateException) etc.
  • Der nachfolgende Code kann (nun) von gültigen Werten ausgehen (braucht diese nicht zu überprüfen), sein Vertrag ist, zu liefern, was die Methode verspricht
  • assert benutze ich als Absicherung bei private-Methoden, in denen eigentlich alles wie gewünscht verlaufen sollte, wo Fehlschläge jedoch nicht ausgeschlossen sind
  • Zukünftig sollte ich automatisierte Tests obligatorisch einsetzen

Noch kürzer: Für jede Methode Vor-, Nachbedingungen und Invarianten ausarbeiten und diese sicherstellen.

Die Nachbedingungen sind auch einen Artikel wert, ich warte auf ein Aha-Erlebnis wie hier.

Wie ich die Ausnahmen dem Benutzer präsentiere, steht im folgenden Artikel.

Ausnahmen:

  • Überschriebene Methoden und implementierte Interfaces, die von Objekten einer anderen Bibliothek aufgerufen werden, beispielsweise vom JDK. Falls diese im Gegensatz zur Dokumentation null überreichen oder ungültige Parameter, liegt ein Defekt in der Bibliothek vor, der von deren Programmieren zu beheben ist.
  • Parameter, die nicht benutzt werden, können einen beliebigen Wert haben, er interessiert nicht.

Stichwörter:

Zu diesem Artikel können keine Kommentare mehr geschrieben werden.