Das Checker Framework - Pluggable Type Systems für Java

Das Checker-Framework - Pluggable Type Systems für Java

1. Überblick

Ab der VersionJava 8 ist es möglich, Programme mit den sogenanntenPluggable Type Systems zu kompilieren, die strengere Prüfungen als die vom Compiler angewendeten durchführen können.

Wir müssen nur die Anmerkungen verwenden, die durch die verfügbaren mehrerenPluggable Type Systems bereitgestellt werden.

In diesem kurzen Artikel werden wirthe 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 unserepom.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 aufMaven Central überprüft werden.

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

Wir müssen dann diemaven-compiler-plugin richtig anpassen, umThe Checker Framework als steckbareType System zu verwenden:


    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 des<annotationProcessors>-Tags. Hier haben wir alle Checker aufgelistet, die wir gegen unsere Quellen ausführen möchten.

3. Vermeiden von NullPointerExceptions

Das erste Szenario, in demThe Checker Framework uns helfen kann, besteht darin, den Code zu identifizieren, aus dem einNullPoinerException 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 erklärt, dass das ArgumentargsvoncountArgs() nicht null sein muss.

Unabhängig von dieser Einschränkung rufen wir inmain() 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 unsThe 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 als Elemente einer Aufzählung.

Nehmen wir an, wir brauchen eine Reihe von Ländern und Planeten. Wir können diese Elemente dann mit der Annotation@Fenumkommentieren, 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 mit Anmerkungen versehen:

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

Aus Versehen können wirgreetPlanet() 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);
}

The 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 die VariableStringeinen regulären Ausdruck mit mindestens einer übereinstimmenden Gruppe speichern muss.

Wir könnenthe 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 wirFIND_NUMBERS zugewiesen haben, keine übereinstimmende Gruppe hat.

In der Tat werdenthe Checker Framework uns beim Kompilieren 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

The 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. Schauen Sie sich die inThe Checker Framework offiziellem Handbuchhere verfügbaren Schecks an oder schreiben Sie sogar Ihre eigenen.

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