2014-11-08 41 views
0

任何人都可以解释为什么循环内的print-statement产生一个错误: (空类型不匹配:要求'@NonNull SortedSet',但提供的值被指定为@Nullable)循环不。难以理解的“空类型不匹配”

我希望这是一个Java错误。是否有解决方案不涉及禁用空检查? (代码没有意义,它只是重现了问题)。

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拍摄。

+1

请发布Utility.getElt()的代码。该方法的返回类型是什么? – 2014-11-08 12:32:39

+0

如果这些注释来自'org.eclipse.jdt.annotation'包,我不认为这是一个Java错误。 'Utility#getElt'的签名是什么? – scriptin 2014-11-08 12:34:01

+0

@PhuongNguyen返回类型在这里没有问题;它是'getElt()'的第二个形式参数的注释,它是'@NonNull SortedSet'。 – 2014-11-08 12:38:31

回答

1

按照documentation,无效分析过程中,

根据本选项,编译器将发出任何错误或只要检测到下列情形之一的警告:

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

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

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

重写与非空注解来声明一个继承的方法的方法,试图通过指定一个可为空的注释(禁止逆变返回)到放宽合同。

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

在上面的表达式被认为是可空的,如果它是静态已知的评估值为null,或者它是用可为空的注释声明的。

(强调增加)。在你的情况,你试图通过Nullable值到NonNull参数。

+0

解释在一次调用中出现的错误的不一致性,而不是另一个---这是实际的问题。 – 2014-11-08 14:00:10

+0

此外,你最后一个引用的句子:“如果一个表达式被认为是可空的,如果它是静态已知的评估为null值---手边的表达式已知*不评估为null *。这几乎使它成为一个不可空的表达式。 – 2014-11-08 14:02:11

+0

也许编译器正在通过循环运行一个额外的时间来优化代码的外部和内部代码的重复?编译的字节码是什么样的? – Jules 2014-11-08 14:12:57

1

更新注释罐子我需要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并不是很古老。