1

过去的手册和 Stackoverflow 的答案都说 NNEL 是 Checker Framework 中的默认值。但是,最近的手册(3.7.1)不再提及该术语。

我在一个包裹上试过这个:

  @DefaultQualifier(value = NonNull.class,
    locations = {TypeUseLocation.RETURN, TypeUseLocation.PARAMETER, TypeUseLocation.FIELD, TypeUseLocation.UPPER_BOUND})

这行得通,但是,我不能声明:

public interface EntryProcessor<K, V, @Nullable R> { }

结果是:

java: [bound.type.incompatible] incompatible bounds in type parameter
  type: R extends @Initialized @NonNull Object
  upper bound: @Initialized @NonNull Object
  lower bound: @Initialized @Nullable null

问题:

  • 现在默认是什么?
  • NNEL 概念是否包含类型参数?
  • 如何module-info.java以尽可能最短的形式为包或更多逻辑为 Java 模块 ( ) 建立 NNEL?
  • 如果 NEEL 不包含类型参数,我怎样才能 EntryProcessor<K, V, @Nullable R>有效地建立默认值EntryProcessor<@NonNull K, @NonNull V, @Nullable R>
4

1 回答 1

1

有一个关于默认的手册部分“未注释类型的默认限定符”。该部分说:

例如,Nullness Checker 的默认限定符是@NonNull. 当用户编写诸如 的非限定类型时Date,Nullness Checker 将其解释为@NonNull Date.

类型系统将该默认限定符应用于大多数但不是所有类型使用。特别是,除非另有说明,否则每个类型系统都使用 CLIMB-to-top 规则。该规则规定,层次结构中的顶级限定符是CLIMB位置的默认值:Casts、Locals和(一些)Implicit B ounds

这类似于旧的“除本地人以外的非 null”描述,但更准确地说明并回答了您关于类型参数的问题。

我怎样才能EntryProcessor<K, V, @Nullable R>有效地建立默认值EntryProcessor<@NonNull K, @NonNull V, @Nullable R>

边界extends Object是隐式的,因此它默认为按照上面提到的 CLIMB-to-top 规则的顶部。(顶部是@NullableNullness Checker 的情况。)这个选择对于源代码中类型的一致处理是必要的。

在您的源代码中,您可以编写@NonNull KK extends ObjectK extends @NonNull Object.

如果您想更改默认值,您提供的代码是正确的:

@DefaultQualifier(value = NonNull.class, locations = {TypeUseLocation.RETURN, TypeUseLocation.PARAMETER, TypeUseLocation.FIELD, TypeUseLocation.UPPER_BOUND})

除了 之外,枚举中UPPER_BOUND还有一个IMPLICIT_UPPER_BOUND值。TypeUseLocation您选择不包含它有什么原因吗?

于 2020-11-07T13:49:58.927 回答