1. 概要

Java 8 リリース以降、いわゆる Pluggable Type Systems を使用してプログラムをコンパイルできるようになりました。これにより、コンパイラーによって適用されるチェックよりも厳密なチェックを適用できます。

利用可能ないくつかのPluggableTypeSystemsによって提供される注釈のみを使用する必要があります。

この簡単な記事では、ワシントン大学の厚意により、チェッカーフレームワークについて説明します。

2. Maven

Checker Frameworkの使用を開始するには、最初に pom.xml:に追加する必要があります。

<dependency>
    <groupId>org.checkerframework</groupId>
    <artifactId>checker-qual</artifactId>
    <version>2.3.2</version>
</dependency>
<dependency>
    <groupId>org.checkerframework</groupId>
    <artifactId>checker</artifactId>
    <version>2.3.2</version>
</dependency>
<dependency>
    <groupId>org.checkerframework</groupId>
    <artifactId>jdk8</artifactId>
    <version>2.3.2</version>
</dependency>

ライブラリの最新バージョンは、 MavenCentralで確認できます。

最初の2つの依存関係には、 Checker Framework のコードが含まれ、後者は Java 8 クラスのカスタムバージョンであり、すべてのタイプがの開発者によって適切に注釈が付けられています。 ]チェッカーフレームワーク

次に、 maven-compiler-plugin を適切に調整して、 CheckerFrameworkをプラグイン可能な型システムとして使用する必要があります。

<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.6.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <compilerArguments>
            <Xmaxerrs>10000</Xmaxerrs>
            <Xmaxwarns>10000</Xmaxwarns>
        </compilerArguments>
        <annotationProcessors>
            <annotationProcessor>
                org.checkerframework.checker.nullness.NullnessChecker
            </annotationProcessor>
            <annotationProcessor>
                org.checkerframework.checker.interning.InterningChecker
            </annotationProcessor>
            <annotationProcessor>
                org.checkerframework.checker.fenum.FenumChecker
            </annotationProcessor>
            <annotationProcessor>
                org.checkerframework.checker.formatter.FormatterChecker
            </annotationProcessor>
        </annotationProcessors>
        <compilerArgs>
            <arg>-AprintErrorStack</arg>
            <arg>-Awarns</arg>
        </compilerArgs>
    </configuration>
</plugin>

ここでの要点は、 鬼ごっこ。 ここに、ソースに対して実行するすべてのチェッカーをリストしました。

3. NullPointerExceptionsの回避

チェッカーフレームワークが役立つ最初のシナリオは、NullPoinerExceptionが発生する可能性のあるコードを特定することです。

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

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

上記の例では、 @NonNull アノテーションを使用して、 countArgs()args引数がnullであってはならないことを宣言しました。

この制約に関係なく、 main()では、 @Nullable で注釈が付けられているため、実際にnullになる可能性のある引数を渡すメソッドを呼び出します。

コードをコンパイルすると、 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);
}

チェッカーフレームワークはエラーを見つけることができます:

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

5. 正規表現

String変数が少なくとも1つの一致するグループを持つ正規表現を格納する必要があることがわかっていると仮定しましょう。

チェッカーフレームワークを活用して、次のような変数を宣言できます。

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

FIND_NUMBERS に割り当てた正規表現には一致するグループがないため、これは明らかに潜在的なエラーです。

実際、チェッカーフレームワークは、コンパイル時にエラーについて熱心に通知します。

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

6. 結論

Checker Framework は、標準のコンパイラーを超えてコードの正確性を向上させたい開発者にとって便利なツールです。

コンパイル時に、通常は実行時にのみ検出できるいくつかの一般的なエラーを検出したり、コンパイルエラーを発生させてコンパイルを停止したりすることができます。

この記事で取り上げたものよりも多くの標準チェックがあります。 チェッカーフレームワークの公式マニュアルここで利用可能なチェックをチェックするか、独自に作成することもできます。

いつものように、このチュートリアルのソースコードは、いくつかの例とともに、GitHubにあります。