3

考虑一下:

@Nullable Object obj = null;
Optional<Object> optional = Optional.ofNullable(obj);

这失败了,因为检查器框架假设ofNullable不能接受null值(毕竟,它的参数没有标记为 @Nullable)。

有没有一种好方法可以告诉检查器框架此方法(或遗留代码中我无法更改的其他方法)在任何地方都接受 @Nullable 类型,而不必在任何地方更改代码?

4

2 回答 2

3

编辑:此答案基于评论中的@mernst 帮助和Checker Framework 的问题跟踪器

如果你和我一样不想或不能使用带注释的 JDK,你会遇到这个问题。

注意:在我工作过的大多数 Java 商店中,我们根本无法切换我们使用的编译器或提供“自定义”JDK(这真是不可想象)。为了使其具有可移植性,我必须将自定义 JDK 添加到我的源存储库中,或者将其分发到每台机器,包括编译代码的 CI 服务器,并确保它们在不同的路径中完全相同操作系统的。只是不酷。

解决方案是提供存根类并将它们作为参数传递给javac进程。

使用您用于编译的任何工具都可以很容易地完成此操作。

例如,使用 Maven(使用标准编译器插件):

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <annotationProcessors>
            <annotationProcessor>org.checkerframework.checker.nullness.NullnessChecker</annotationProcessor>
         </annotationProcessors>
         <compilerArgs>
             <arg>-Astubs=checkerframework/stubs</arg>
             <arg>-AstubWarnIfNotFound</arg>
         </compilerArgs>
     </configuration>
 </plugin>

您还需要将这些依赖项添加到您的项目中:

    <dependency>
        <groupId>org.checkerframework</groupId>
        <artifactId>checker-qual</artifactId>
        <version>1.9.2</version>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.checkerframework</groupId>
        <artifactId>checker</artifactId>
        <version>1.9.2</version>
        <optional>true</optional>
    </dependency>

这里,checkerframework/stubs是一个目录(相对于 pom 的位置),包含stubs。对于 Optional,我的 stub 看起来像这样(奇怪的是,stub 必须命名为 *.astub,所以这个文件称为 Optional.astub):

package java.util;

import org.checkerframework.checker.interning.qual.*;

import javax.annotation.Nullable;

class Optional<T> {
    static <T> Optional<T> ofNullable(@Nullable T value);

    @Nullable T orElse(@Nullable T other);
}

这种方法很简单,只需要很少的工作,根本不会混淆我使用的编译器或 Java 库,确保这些定义仅与 checkerframework 一起使用(例如,我可以将其添加到 Maven 配置文件并启用只有当我想通过简单地传递一个 Maven 参数时,它才会跨机器和操作系统工作,而无需事先设置,以真正的 Java 做事方式。

于 2015-07-02T07:50:34.020 回答
0

我不确定您为什么说“其参数未标记为@Nullable”。当我查看文件 checker-framework/checker/jdk/nullness/src/java/util/Optional.java 时,我看到以下带注释的方法:

public static <T> Optional<@NonNull T> ofNullable(@Nullable T value) {
    return value == null ? empty() : of(value);
}

此外,当我在以下代码上运行 Checker Framework 时,它不会发出任何警告。

// run like this:
// javacheck -g TestOptional.java -processor nullness

import java.util.*;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.checkerframework.checker.nullness.qual.NonNull;

public class TestOptional {

  void m() {

    @Nullable Object obj = null;
    Optional<Object> optional1 = Optional.ofNullable(obj);

  }

}

我不确定你的情况发生了什么,因为你没有提供完整的测试用例,你没有说你运行了什么命令,也没有给出实际的错误消息。(您确实提供了诊断,但我不确定它是否准确。)

也许提供更多细节可以更好地理解您的问题。

于 2015-07-02T00:27:01.593 回答