难以理解的“空类型不匹配”

时间:2014-11-08 12:25:04

标签: java

任何人都可以解释为什么循环中的print语句会产生错误 (空类型不匹配:需要'@NonNull SortedSet',但提供的值指定为@Nullable),循环外的值不是。

我希望这是一个Java bug。是否有解决方法不涉及禁用nullcheck? (代码没有意义,它只是重现了问题)。

public class Test
{
  static void print(PrintStream ps, @Nullable SortedSet<IState> states)
  {
    if (states != null)
    {
      ps.print(Utility.getElt(0, states));
    }
    for (int q = 0; q < 1; q++)
    {
      if (states != null)
      {
        ps.print(Utility.getElt(0, states));
      }
    }
  }
}

Utility.getElt具有以下签名:

public static <@Nullable T> T getElt(int idx, @NonNull SortedSet<T> set);

如果我删除了getElt的@NonNull注释,问题就会消失,但我真的想要一个非空的“设置”。

实际上注释来自org.eclipse.jdt.annotation。

2 个答案:

答案 0 :(得分:1)

根据documentation,在零分析期间,

  

根据此选项,只要检测到以下某种情况,编译器就会发出错误或警告:

     
    

使用非空注释声明的方法返回可为空的表达式。

         

可以为空的表达式作为参数传递给方法调用,其中使用非空注释声明被调用方法的相应参数。

         

可为空的表达式分配给使用非空注释声明的局部变量。

         

重写使用非空注释声明的继承方法的方法尝试通过指定可为空的注释(禁止逆变返回)来放宽该约定。

         

重写一个对其至少一个参数具有可空声明的继承方法的方法,尝试通过为其相应参数指定非空注释来加强该空契约(禁止协变参数)。

  
     

在上面,如果一个表达式被静态地知道为值null,或者它是用可空的注释声明的,那么它被认为是可为空的。

(重点补充)。在您的情况下,您尝试将Nullable值传递给NonNull参数。

答案 1 :(得分:1)

将注释jar更新到最新版本(?)之后我需要更改getElt的签名

public static <@Nullable T> T getElt(int idx, @NonNull SortedSet<T> set);

public static @Nullable <T> T getElt(int idx, @NonNull SortedSet<T> set);

以前的语法不再有效。

这并没有解决问题,但至少现在有一个通过显式转换的解决方法(仍然只需要循环内的版本!):

    ps.print(Utility.getElt(q, (@NonNull SortedSet<IState>)states));

虽然这会产生精彩的警告 “从SortedSet到SortedSet的不必要的强制转换”,现在只是一个警告,而不是错误。

Eclipse中的这种空值检查似乎仍然非常“正在进行中”。 我之前版本的注释jar不是很老。