@NonNull和@Nullable的正确用法是什么?

时间:2015-08-15 14:55:07

标签: java android annotations

我对这些注释的正确使用感到困惑。

android.support.annotation.NonNull;
android.support.annotation.Nullable;

@NonNull文档中的信息说:

  

表示参数,字段或方法返回值永远不能为空。

这对参数来说意味着什么,什么时候没有什么可以阻止你通过null

例如,假设我有一个类MyObject,并且一个实例可能有也可能没有标题。

public final class MyObject {

    private String title = null;

    public void setTitle(String title) {
        if (title == null)
            throw new NullPointerException();
        this.title = title;
    }

    public void clearTitle() {
        title = null;
    }
}

这里我使用null来表示标题的缺失,但这是一个实现细节,因此我不想要一种方法来设置和清除标题。

如果我将字段title标记为@Nullable,android studio会告诉我setTitle的参数也应该标记为@Nullable(但这与我想要的是什么。

如果我将setTitle方法的参数标记为@NonNull,我会收到警告,条件title == null始终为false

在这种情况下,这些注释的正确用法是什么?如果@NonNull表示参数 永远不会是null,那么使用它来表示应该不是null是错误的吗?如果是,是否有正确的方法来表明这一点?

4 个答案:

答案 0 :(得分:1)

@Nonnull@Nullable是声明性的。这是对软件开发人员的暗示。你告诉他们,参数可以是空值,也可以不是。

如果您使用@Nonnull注释标记参数,则告诉每个使用您的API的人,他们不应在此处传递空值,否则他们必须处理后果(例如NullPointerException

您可以使用它来声明,参数SHOULD不应为null,在我看来这是一个有效的用例。

答案 1 :(得分:1)

关键是这个注释是某种契约,所以如果你正确地宣布你的方法,你就不需要进行检查。 Android Studio会检查您是否不熟悉它。您仍然可以忽略它,但这会导致编译器警告。

如果省略无用(通过合同)安全检查,它将正确抛出nullpointerexceptions。但开发人员收到了您的注释警告。

答案 2 :(得分:1)

如果标记参数@NonNull,则需要方法的用户进行空检查,因为@NonNull不会在运行时捕获NPE。因此,例如,如果你有一个带有辅助方法的实用程序类在执行之前检查null,那么你会将这些参数标记为@Nullable,因为你在技术上可以传递一个空值,但是可以安全地检查它。

答案 3 :(得分:0)

继续将setTitle方法的参数标记为@NonNull

这将确保编译器在某些代码调用setTitle并且值可能为空时发出错误。因此,编译器确保setTitle 从不调用null。因此,您可以删除方法中的null检查,使'title == null始终为false'警告消失。

即。你的代码看起来像这样:

public final class MyObject {

    private String title = null;

    public void setTitle(@NonNull String title) {
        this.title = title;
    }

    public void clearTitle() {
        title = null;
    }
}

(注意:我没有使用Android Studio,但我猜它的行为与Eclipse类似。在Eclipse中,当我尝试将null或表达式传递给setTitle时,我得到一个错误Null type mismatch: required '@NonNull String' but the provided value is null(/inferred as @Nullable)。)

顺便说一句:同时使用title注释字段@Nullable的定义会使其更明确title也可能包含null值。