Checker Framework - Сменяеми системи от тип за Java

1. Общ преглед

От изданието на Java 8 нататък е възможно да се компилират програми с помощта на така наречените Pluggable Type Systems - които могат да прилагат по-строги проверки от прилаганите от компилатора.

Трябва само да използваме анотациите, предоставени от няколкото налични системи с подвижен тип .

В тази кратка статия ще разгледаме рамката за проверка с любезното съдействие на Университета във Вашингтон.

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, за да използваме Checker Framework като подвижна система тип :

 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   

Основното тук е съдържанието на етикет. Тук изброихме всички пулове, които искаме да пуснем срещу нашите източници.

3. Избягване на NullPointerExceptions

Първият сценарий, в който 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 () не трябва да е null.

Независимо от това ограничение, в main () ние извикваме метода, предаващ аргумент, който наистина може да бъде нулев, тъй като е бил анотиран с @Nullable .

Когато компилираме кода, 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); }

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 трябва да съхранява регулярен израз с поне една съвпадаща група.

Можем да използваме Checker Framework и да декларираме такава променлива по този начин:

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

Това очевидно е потенциална грешка, тъй като регулярният израз, който присвоихме на FIND_NUMBERS, няма съвпадаща група.

Всъщност, Checker Framework ще ни информира усърдно за нашата грешка по време на компилация:

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

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

Checker Framework е полезен инструмент за разработчици, които искат да надхвърлят стандартния компилатор и да подобрят коректността на своя код.

Той може да открие по време на компилация няколко типични грешки, които обикновено могат да бъдат открити само по време на изпълнение или дори да спрат компилацията чрез повишаване на грешка при компилация.

Има много повече стандартни проверки от това, което разгледахме в тази статия; проверете чековете, налични в официалното ръководство на Checker Framework тук, или дори напишете свои собствени.

Както винаги, изходният код за този урок, с още няколко примера, може да бъде намерен в GitHub.