1概要


Java 8

リリース以降、いわゆるhttps://docs.oracle.com/javase/tutorial/java/annotations/type

annotations.html[

Pluggable Type Systems__]を使用してプログラムをコンパイルすることができます。コンパイラによって適用されるもの。

利用可能ないくつかのPluggable Type Systems__によって提供されるアノテーションを使用するだけです。

このクイック記事では、ワシントン大学の好意により、


the Checker Framework


について説明します。


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>

ライブラリの最新版はhttps://search.maven.org/classic/#search%7C1%7Cg%3A%22org.checkerframework%22%20AND%20a%3A%22checker%22[Mavenで確認できます。中央]。

最初の2つの依存関係は

The Checker Framework

のコードを含み、後者は

Java 8

クラスのカスタムバージョンで、すべての型は

The Checker Framework

の開発者によって適切に注釈が付けられています。

次に、

The Checker Framework

をプラグイン可能な

Type System

として使用するために

maven-compiler-plugin

を適切に調整する必要があります。

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

ここでの要点は

<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

アノテーションを使用して、

countArgs()



args

引数をnullにしないように宣言しました。

この制約に関係なく、

main()

では、

@ Nullable

のアノテーションが付けられているので、実際にnullになる可能性がある引数を渡してメソッドを呼び出します。

コードをコンパイルするとき、

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

変数が少なくとも1つの一致するグループを含む正規表現を格納する必要があることを私たちが知っているとしましょう。

Checker Framework__を利用して、そのような変数を次のように宣言できます。

@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は、標準のコンパイラを超えてコードの正当性を高めたい開発者にとって便利なツールです。

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

この記事で取り上げたものよりも多くの標準的なチェックがあります。

The Checker Framework

公式マニュアルhttps://checkerframework.org/manual/[ここ]で利用可能なチェックをチェックするか、あるいはあなた自身で書いてください。

いつものように、このチュートリアルのソースコードは、他にもいくつか例がありますが、https://github.com/eugenp/tutorials/tree/master/checker-plugin/[over on GitHub]にあります。