Одним из интересных инструментов, о которых я узнал на JavaOne 2012, является The Checker Framework . На одной из веб-страниц Checker Framework утверждается, что Checker Framework «улучшает систему типов Java, делая ее более мощной и полезной,» позволяя разработчикам программного обеспечения «обнаруживать и предотвращать ошибки в своих программах Java». Один из способов взглянуть на Checker Framework — это реализация того, что JSR 305 («Аннотации для обнаружения дефектов программного обеспечения») могла бы не попасть в стадию бездействия .
Цель JSR 308 («Аннотации в типах Java») состоит в том, чтобы «расширить синтаксис аннотаций Java, чтобы разрешить аннотации в любом случае типа». Как только JSR 308 будет утвержден и станет частью языка программирования Java, аннотации будут разрешены там, где они в настоящее время не разрешены. Хотя JSR 308 все еще находится на этапе раннего предварительного просмотра 2 , Checker Framework позволяет разработчику включать закомментированный код аннотации в тех местах, которые в настоящее время не разрешены до тех пор, пока не станут доступны в JSR 308. Здесь важно отметить, что JSR 308 делает аннотации только в более общем виде. доступный (указывает больше типов исходного кода, к которому они могут быть применены) и не указывает никаких новых аннотаций.
Для Checker Framework требуется Java SE 6 или более поздняя версия. Среду Checker Framework можно загрузить в виде одного ZIP-файла по адресу http://types.cs.washington.edu/checker-framework/current/checkers.zip . Загруженный файл может быть разархивирован в платформу проверки каталогов, а затем может быть установлена переменная среды CHECKERS, указывающая на подкаталог этого расширенного каталога «checkers». Например, если файл checkers.zip разархивирован в C: \ checker-framework, для переменной среды CHECKERS должно быть установлено C: \ checker-framework \ checkers.
Когда Checkers Framework checkers.zip был загружен, расширен и указан переменной среды CHECKERS, пришло время попробовать Checker Framework. Далее показан «длинный путь» запуска Checker Framework, который используется с тегом -version для проверки того, что Checker Framework применяется:
Windows
java -Xbootclasspath/p:%CHECKERS%/binary/jsr308-all.jar -jar %CHECKERS%/binary/jsr308-all.jar -version
Linux
java -Xbootclasspath/p:$CHECKERS/binary/jsr308-all.jar -jar $CHECKERS/binary/jsr308-all.jar -version
Вышеуказанное должно привести к выводу, который будет выглядеть примерно так, как показано на следующем снимке экрана.
Установленная Checker Framework теперь может быть применена для компиляции кода. В следующем листинге кода показан простой класс, который указывает, что аргумент метода не должен быть нулевым с помощью аннотации checkers.nullness.quals.NonNull ( @NonNull ).
package dustin.examples; import checkers.nullness.quals.NonNull; import static java.lang.System.out; public class CheckersDemo { public void printNonNullToString(@NonNull final Object object) { out.println(object.toString()); } public static void main(final String[] arguments) { final CheckersDemo me = new CheckersDemo(); final String nullStr = null; me.printNonNullToString(nullStr); } }
Приведенный выше листинг кода показывает, что в метод передается значение NULL с аргументом, аннотированным @NonNull. NetBeans 7.3 помечает это желтыми загогулинами и предупреждает, если наведен. Это показано на следующих снимках экрана.
Хотя NetBeans помечает нулевое значение параметра, помеченного аннотацией @NonNull, компилятор создает этот код без жалоб. Вот тут-то и вступает Checker Framework. Поскольку вводить длинную команду, которую я показывал ранее, очень сложно, я либо запускаю указанную выше команду со скриптом, либо устанавливаю псевдоним, как описано в инструкциях по установке Checker Framework . В этом случае я буду использовать псевдоним:
Настройка псевдонима командной строки Windows для проверки Java
doskey javachecker=java -Xbootclasspath/p:%CHECKERS%\binary\jsr308-all.jar -jar %CHECKERS%\binary\jsr308-all.jar $*
Настройка этого псевдонима и запуск его с флагом -version продемонстрирован на следующем снимке экрана.
Гораздо проще применить этот подход с набором псевдонимов. Это может быть использовано для компиляции рассматриваемого класса, как показано ниже (команда, использующая мой псевдоним ‘javachecker’ и изображение, показывающее результат).
javachecker -d classes src\dustin\examples\*.java
Приведенная выше команда демонстрирует, что я могу использовать обычные параметры javac, такие как -d, чтобы указать каталог назначения для скомпилированных файлов .class и передать исходные файлы Java для компиляции в обычном режиме. В этом примере также показано, что без указания процессора проверки для запуска в процессе компиляции дополнительная типизация @NotNull не применяется во время компиляции.
Прежде чем показать, как указать процессор для принудительного применения @NonNull во время компиляции, я хочу быстро продемонстрировать, что этот подход к компиляции будет по-прежнему сообщать о стандартных ошибках компилятора. Как раз для этого примера я переименовал переменную «nullStr», переданную интересующему методу в строке 17, в «nullStry», чтобы это было ошибкой компилятора. На следующих двух снимках экрана показано это изменение (и сообщенная ошибка компиляции NetBeans) и то, как подход компиляции Checker Framework также сообщает об ошибке javac.
Показав, что этот подход к компиляции нормально компилирует компилируемый код, нормально сообщает об ошибках компилятора и соответствующим образом показывает версию, пришло время применить его для более строгого применения типов. Я исправляю ошибку компилятора в своем коде, удаляя лишние «y», которые я добавил. Затем мне нужно передать -processor checkers.nullness.NullnessChecker в качестве дополнительного флага и аргумента процесса компиляции. Обратите внимание, что есть и другие процессоры, кроме NullnessChecker , но я использую NullnessChecker здесь для принудительного применения @NonNull во время компиляции.
Ниже показана команда вместе с окном вывода, демонстрирующее эту команду в действии. Обратите внимание, что процесс компиляции не может быть завершен, и сообщается об ошибке, связанной с нарушением типизации @NonNull.
javachecker -processor checkers.nullness.NullnessChecker -d classes src\dustin\examples\*.java
В этом сообщении в блоге рассказывается о Checker Framework и показано, как быстро применить его для более строгого соблюдения типов в исходном коде Java. Здесь я сосредоточился только на одном типе более строгой типизации, но Checker Framework предоставляет другие встроенные проверки типов и поддерживает возможность написания пользовательских проверок принудительного исполнения типов.