Das Checker Framework - Pluggable Type Systems für Java

1. Übersicht

Ab der Java 8- Version ist es möglich, Programme mit den sogenannten Pluggable Type Systems zu kompilieren, die strengere Prüfungen anwenden können als die vom Compiler angewendeten.

Wir müssen nur die Anmerkungen verwenden, die von den verschiedenen verfügbaren steckbaren Typsystemen bereitgestellt werden.

In diesem kurzen Artikel werden wir das Checker Framework mit freundlicher Genehmigung der University of Washington untersuchen.

2. Maven

Um mit dem Checker Framework arbeiten zu können, müssen wir es zuerst in unsere pom.xml einfügen:

 org.checkerframework checker-qual 2.3.2   org.checkerframework checker 2.3.2   org.checkerframework jdk8 2.3.2 

Die neueste Version der Bibliotheken kann in Maven Central überprüft werden.

Die ersten beiden Abhängigkeiten enthalten den Code von The Checker Framework, während letztere eine benutzerdefinierte Version der Java 8- Klassen ist, in der alle Typen von den Entwicklern von The Checker Framework ordnungsgemäß mit Anmerkungen versehen wurden .

Wir haben dann richtig die zwicken Maven-Compiler-Plugin zu verwenden , die Checker - Framework als steckbarer Typ - System :

 maven-compiler-plugin 3.6.1  1.8 1.8  10000 10000    org.checkerframework.checker.nullness.NullnessChecker   org.checkerframework.checker.interning.InterningChecker   org.checkerframework.checker.fenum.FenumChecker   org.checkerframework.checker.formatter.FormatterChecker    -AprintErrorStack -Awarns   

Der Hauptpunkt hier ist der Inhalt der Etikett. Hier haben wir alle Prüfer aufgelistet, die wir gegen unsere Quellen ausführen möchten.

3. Vermeiden von NullPointerExceptions

Das erste Szenario, in dem uns das Checker Framework helfen kann, besteht darin, die Codes zu identifizieren, aus denen eine NullPoinerException stammen könnte:

private static int countArgs(@NonNull String[] args) { return args.length; } public static void main(@Nullable String[] args) { System.out.println(countArgs(args)); }

Im obigen Beispiel haben wir mit der Annotation @NonNull deklariert, dass das Argument args von countArgs () nicht null sein darf.

Unabhängig von dieser Einschränkung rufen wir in main () die Methode auf, die ein Argument übergibt, das tatsächlich null sein kann, da es mit @Nullable kommentiert wurde .

Wenn wir den Code kompilieren, warnt uns das Checker Framework ordnungsgemäß, dass etwas in unserem Code falsch sein könnte:

[WARNING] /checker-plugin/.../NonNullExample.java:[12,38] [argument.type.incompatible] incompatible types in argument. found : null required: @Initialized @NonNull String @Initialized @NonNull []

4. Richtige Verwendung von Konstanten als Aufzählungen

Manchmal verwenden wir eine Reihe von Konstanten, da sie Elemente einer Aufzählung waren.

Nehmen wir an, wir brauchen eine Reihe von Ländern und Planeten. Wir können diese Elemente dann mit der Annotation @Fenum kommentieren , um alle Konstanten zu gruppieren, die Teil derselben „falschen“ Aufzählung sind:

static final @Fenum("country") String ITALY = "IT"; static final @Fenum("country") String US = "US"; static final @Fenum("country") String UNITED_KINGDOM = "UK"; static final @Fenum("planet") String MARS = "Mars"; static final @Fenum("planet") String EARTH = "Earth"; static final @Fenum("planet") String VENUS = "Venus";

Wenn wir danach eine Methode schreiben, die einen String akzeptieren soll, der ein „Planet“ ist, können wir das Argument richtig kommentieren:

void greetPlanet(@Fenum("planet") String planet){ System.out.println("Hello " + planet); }

Aus Versehen können wir greetPlanet () mit einer Zeichenfolge aufrufen , die nicht als möglicher Wert für einen Planeten definiert wurde, z.

public static void main(String[] args) { obj.greetPlanets(US); }

Das Checker Framework kann den Fehler erkennen:

[WARNING] /checker-plugin/.../FakeNumExample.java:[29,26] [argument.type.incompatible] incompatible types in argument. found : @Fenum("country") String required: @Fenum("planet") String

5. Reguläre Ausdrücke

Nehmen wir an, wir wissen, dass eine String- Variable einen regulären Ausdruck mit mindestens einer übereinstimmenden Gruppe speichern muss.

Wir können das Checker Framework nutzen und eine solche Variable wie folgt deklarieren:

@Regex(1) private static String FIND_NUMBERS = "\\d*";

Dies ist offensichtlich ein potenzieller Fehler, da der reguläre Ausdruck, den wir FIND_NUMBERS zugewiesen haben, keine übereinstimmende Gruppe enthält.

In der Tat wird uns das Checker Framework bei der Kompilierung sorgfältig über unseren Fehler informieren:

[WARNING] /checker-plugin/.../RegexExample.java:[7,51] [assignment.type.incompatible] incompatible types in assignment. found : @Regex String required: @Regex(1) String

6. Fazit

Das Checker Framework ist ein nützliches Tool für Entwickler, die über den Standard-Compiler hinausgehen und die Korrektheit ihres Codes verbessern möchten.

Es kann zur Kompilierungszeit mehrere typische Fehler erkennen, die normalerweise nur zur Laufzeit erkannt werden können, oder sogar die Kompilierung stoppen, indem ein Kompilierungsfehler ausgelöst wird.

Es gibt viel mehr Standardprüfungen als in diesem Artikel beschrieben. Lesen Sie hier die im offiziellen Handbuch des Checker Framework verfügbaren Schecks oder schreiben Sie sogar Ihre eigenen.

Wie immer finden Sie den Quellcode für dieses Tutorial mit einigen weiteren Beispielen auf GitHub.