The Checker Framework - Системы сменных типов для Java

Среда проверки - системы сменных типов для Java

1. обзор

Начиная с версииJava 8, можно компилировать программы, используя так называемыйPluggable Type Systems, который может применять более строгие проверки, чем те, которые применяются компилятором.

Нам нужно только использовать аннотации, предоставленные несколькими доступнымиPluggable Type Systems.

В этой быстрой статье мы рассмотримthe Checker Framework, любезно предоставленные Вашингтонским университетом.

2. специалист

Чтобы начать работу с Checker Framework, нам нужно сначала добавить его в нашpom.xml:


    org.checkerframework
    checker-qual
    2.3.2


    org.checkerframework
    checker
    2.3.2


    org.checkerframework
    jdk8
    2.3.2

Последнюю версию библиотек можно проверить наMaven Central.

Первые две зависимости содержат кодThe Checker Framework, в то время как последняя представляет собой настраиваемую версию классовJava 8, в которой все типы должным образом аннотированы разработчикамиThe Checker Framework.

Затем мы должны правильно настроитьmaven-compiler-plugin, чтобы использоватьThe Checker Framework в качестве подключаемогоType 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
        
    

Главное здесь - это содержимое тега<annotationProcessors>. Здесь мы перечислили все шашки, которые мы хотим запустить против наших источников.

3. Как избежать исключений NullPointerExceptions

Первый сценарий, в которомThe Checker Framework может помочь нам, - это определение фрагмента кода, из которого может возникнутьNullPoinerException:

private static int countArgs(@NonNull String[] args) {
    return args.length;
}

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

В приведенном выше примере мы объявили с аннотацией@NonNull, что аргументargs дляcountArgs() не должен быть нулевым.

Независимо от этого ограничения вmain() мы вызываем метод, передавая аргумент, который действительно может иметь значение NULL, потому что он аннотирован@Nullable.

Когда мы компилируем код,The Checker Framework должным образом предупреждает нас, что что-то в нашем коде может быть неправильным:

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

4. Правильное использование констант в качестве перечислений

Иногда мы используем серию констант, поскольку они были элементами перечисления.

Предположим, нам нужен ряд стран и планет. Затем мы можем аннотировать эти элементы аннотацией@Fenum, чтобы сгруппировать все константы, которые являются частью одного и того же «поддельного» перечисления:

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";

После этого, когда мы пишем метод, который должен принимать строку, которая является «планетой», мы можем правильно аннотировать аргумент:

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

По ошибке мы можем вызватьgreetPlanet() со строкой, которая не была определена как возможное значение для планеты, например:

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

The Checker Framework может обнаружить ошибку:

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

5. Регулярные выражения

Предположим, мы знаем, что переменнаяString должна хранить регулярное выражение хотя бы с одной совпадающей группой.

Мы можем использоватьthe Checker Framework и объявить такую ​​переменную вот так:

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

Это, очевидно, потенциальная ошибка, потому что регулярное выражение, которое мы присвоилиFIND_NUMBERS, не имеет подходящей группы.

Действительно,the Checker Framework будет старательно сообщать нам о нашей ошибке во время компиляции:

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

6. Заключение

The Checker Framework - полезный инструмент для разработчиков, которые хотят выйти за рамки стандартного компилятора и улучшить правильность своего кода.

Он способен обнаруживать во время компиляции несколько типичных ошибок, которые обычно могут быть обнаружены только во время выполнения, или даже останавливать компиляцию, вызывая ошибку компиляции.

Стандартных проверок намного больше, чем мы рассмотрели в этой статье; проверьте проверки, доступные в официальном руководствеThe Checker Frameworkhere, или даже напишите свой собственный.

Как всегда, исходный код этого руководства с дополнительными примерами можно найти вover on GitHub.