使用java检查器框架,为什么非空键不被接受到可空键位置?

问题描述 投票:0回答:1

使用java检查器框架,为什么Map NonNull键不被接受到Map Nullable键位置?

通过此代码调用:

        schema.validate(
            MapMaker.makeMap(
                new AbstractMap.SimpleEntry<>(
                    "foo",
                    "baz"
                ),
                new AbstractMap.SimpleEntry<>(
                    "bar",
                    2
                )
            ),
            configuration
        );

我收到此错误:

java: [argument] incompatible argument for parameter arg of validate.
  found   : @Initialized @NonNull Map<@Initialized @NonNull String, @Initialized @NonNull Object>
  required: @Initialized @NonNull Map<@Initialized @NonNull String, @Initialized @Nullable Object>

验证方法定义为:

public FrozenMap<@Nullable Object> validate(Map<String, @Nullable Object> arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException {

任何非 null 对象都是可为 null 对象集合的子集,那么为什么这不起作用呢? 如何让它也适用于不可为空的键输入? 我是否需要为可为空和不可为空的输入参数使用不同的输入方法签名?

我传递给验证方法的参数将仅用于读取。根据检查器框架 javadocs,@Covariant 可能是这里的一个解决方案:

For example, consider Iterator. A client can read elements but not write them, so Iterator<@Nullable String> can be a subtype of Iterator<String> without introducing a hole in the type system. Therefore, its type parameter is annotated with @Covariant. The first type parameter of Map.Entry is also covariant. Another example would be the type parameter of a hypothetical class ImmutableList.

但这仅适用于接口。

java null typechecking checker-framework
1个回答
0
投票

之所以发生这种情况是因为检查器框架看到了

  • 字符串
  • @可为空字符串 作为两个不同的类,其中 String (@NonNull String) 继承自 @Nullable string 与普通 Java 一样,协方差不适用。

所以这里的解决方案是:

  1. 更新验证方法以接受 Map 这不太好,因为签名中丢失了类型检查信息
  2. 或者编写许多接受带/不带 @Nullable 的所有组合的方法,例如
    Map<String, @Nullable Object> arg
    Map<String, Object> arg
  3. 或者编写一个接口,为每个可为空的参数创建一个泛型参数,并实现它。

第 3 号示例代码如下所示

@Covariant(0)
public interface MapValidator <@Nullable InType, OutType> {
    OutType validate(Map<String, InType> arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException;
}

public class SomeSchema implements MapValidator<@Nullable Object, FrozenMap<@Nullable Object>> {
    OutType validate(Map<String, @Nullable Object> arg, SchemaConfiguration configuration) throws ValidationException, InvalidTypeException {
        ...
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.