IntelliJ IDEA报告合同违规警告

jn1*_*1kk 7 java intellij-idea

这是Java代码:

public static boolean anyEqual(Object needle, Object... haystack) {
    if(needle == null || haystack == null) {
        return false;
    }
    if(haystack.length == 0) {
        return false;
    }
    for(Object match : haystack) {
        if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
            return true; // warning from IntelliJ here, 'contract clause !null, null -> false is violated'
        }
    }
    return false;
}
Run Code Online (Sandbox Code Playgroud)

有没有人知道为什么要显示它?contract clause !null, null -> false is violated?谢谢!

IntelliJ 14.0.2 build:139.659

截图: 在此输入图像描述

Mak*_*oto 5

IntelliJ推断你的方法的正式合同是这样的:

null, _ -> false; !null, null -> false
Run Code Online (Sandbox Code Playgroud)

这实际意味着什么:

  • 第一个合同指定,只要第一个参数是null,它就会返回false.您的第一个if声明就是这样:

    if(needle == null || haystack == null) {
        return false;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 第二个合同指定,如果第二个参数是null,则它将返回false.这也由if上面的相同声明指定.

我的直觉告诉我,除了上述所有内容之外,IntelliJ在识别循环的正式合同方面遇到了一些麻烦,尽管它与合同表达式中的另一个条件一样简单.

for(Object match : haystack) {
    if(match != null && needle.getClass() == match.getClass() && needle.equals(match)) {
        return true;
    }
}
Run Code Online (Sandbox Code Playgroud)

让我们简要介绍一下.

  • 如果haystack长度为0,则不会触发enhanced-for语句,因此需要考虑这一点.
  • 数组内部的元素可能是null,我不完全确定IntelliJ的静态分析还涵盖了那个部分.
  • 我们已经确定needle必须是非空的,所以没有违反合同的那条线.
  • 如果我们有一个场景,其中match != null && needle.getClass() == match.getClass() && needle.equals(match)true,我们返回true.否则,我们回来false.

什么我可以正式文档中看到,才使我们需要说的,表达"哎-我们正在检查的数组中的元素!" 可能的情况是true,尽管我们上面已经说过(因为haystack非空),但我们正在返回这一事实.

请允许我强调这一点:

haystack必须不是null为了让你进入增强型. 您的代码将无法正常工作.

总而言之,我不担心.更好的是,提交一个针对它的错误,以便可以修复或扩展此类事情.