我已经开始注释我的程序,编写nullness注释。按照指南,我已经注释了我的一个类并将其标记为@AnnotatedFor({"nullness"})
。该程序使用Oracle JDK 1.7.u21在Java 7平台下编译(由于某些技术限制,无法切换到JDK 8)。
该类使用了一堆未经纳米化的第三方(Google Guava)和JDK库方法,因此我在Maven编译器插件参数中包含选项-AskipUses=...
和-AuseSafeDefaultsForUnnanotatedSourceCode
,如下所示:
<properties>
<project.checker.annotatedJdk>${org.checkerframework:jdk7:jar}</project.checker.annotatedJdk>
<project.checker.typeAnnotationsJavac>${org.checkerframework:compiler:jar}</project.checker.typeAnnotationsJavac>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
<executions>
<execution>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<fork>true</fork>
<annotationProcessors>
<annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor>
</annotationProcessors>
<compilerArgs>
<arg>-Xbootclasspath/p:${project.checker.annotatedJdk}</arg>
<arg>-J-Xbootclasspath/p:${project.checker.typeAnnotationsJavac}</arg>
<arg>-AuseSafeDefaultsForUnannotatedSourceCode</arg>
<arg>-AskipUses=com\.google\.common\.|java\.math</arg>
</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>
该类的源代码:
package pkg;
import java.util.*;
import java.math.BigDecimal;
import com.google.common.base.*;
import com.google.common.collect.Ordering;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.framework.qual.AnnotatedFor;
@AnnotatedFor({"nullness"})
public class Indicator implements Comparable<Indicator> {
private static final BigDecimal DEFAULT_SORT_ORDER;
private static final Ordering<Indicator> ORDERING;
public static enum IndicatorComparator implements Comparator<Indicator> {
INSTANCE;
@Override
public final int compare(Indicator left, Indicator right) {
/* nulls-last */
if (left.sortOrder != null && right.sortOrder != null) {
return left.sortOrder.compareTo(right.sortOrder);
} else if (left.sortOrder != null && right.sortOrder == null) {
return -1;
} else if (left.sortOrder == null && right.sortOrder != null) {
return 1;
} else {
return 0;
}
}
}
static {
DEFAULT_SORT_ORDER = BigDecimal.valueOf(0.0);
ORDERING = Ordering.from(IndicatorComparator.INSTANCE).nullsLast();
}
private final int id;
private @Nullable String code;
private @Nullable BigDecimal sortOrder;
private boolean isGroup;
private Indicator(Builder builder) {
id = builder.id;
code = builder.code;
sortOrder = builder.sortOrder;
isGroup = builder.isGroup;
}
/* equals and hashcode are not overriden by purpose -- the default version will do */
@Override
public int compareTo(final Indicator other) {
return ORDERING.compare(this, other);
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("id", id)
.add("code", code)
.add("sortOrder", sortOrder)
.add("isGroup", isGroup)
.toString();
}
public int getId() {
return id;
}
public Optional<String> getCode() {
return Optional.fromNullable(code);
}
public Optional<BigDecimal> getSortOrder() {
return Optional.fromNullable(sortOrder);
}
public boolean isGroup() {
return isGroup;
}
public void setCode(@Nullable String code) {
this.code = code;
}
public void setSortOrder(@Nullable BigDecimal sortOrder) {
this.sortOrder = sortOrder;
}
public void setGroup(boolean group) {
this.isGroup = group;
}
public static class Builder {
private int id;
private @Nullable String code;
private @Nullable BigDecimal sortOrder;
private boolean isGroup;
public Builder() {
sortOrder = DEFAULT_SORT_ORDER;
}
public Builder id(int id) {
this.id = id;
return this;
}
public Builder code(@Nullable String code) {
this.code = code;
return this;
}
public Builder sortOrder(@Nullable BigDecimal sortOrder) {
this.sortOrder = sortOrder;
return this;
}
public Builder isGroup(boolean isGroup) {
this.isGroup = isGroup;
return this;
}
public Indicator build() {
return new Indicator(this);
}
}
}
当我构建项目时,Checker似乎忽略了'skip'选项,因为我最终遇到了像
这样的错误COMPILATION ERROR :
-------------------------------------------------------------
pkg/Indicator.java:[38,48] error: [argument.type.incompatible] incompatible types in argument.
found : @UnknownKeyFor double
required: @KeyForBottom double
引导我们进入第38行:
DEFAULT_SORT_ORDER = BigDecimal.valueOf(0.0);
或39:
pkg/Indicator.java:[39,52] error: [argument.type.incompatible] incompatible types in argument.
found : IndicatorComparator
required: Comparator<Indicator>
再次或38:
pkg/Indicator.java:[38,47] error: [assignment.type.incompatible] incompatible types in assignment.
found : @UnknownInitialization @Nullable BigDecimal
required: @Initialized @NonNull BigDecimal
等等 - 日志中出现了各种检查错误,但我认为我已经使用-AskipUses=
选项删除了它们。
我做错了吗?
UPD 07.12.2015:附上了该课程的完整源代码。 UPD 14.12.2015:更新了源代码,因此现在重现案例要容易得多。