IntelliJ 显示 "always true" 提示但不显示 "always false" instanceof

IntelliJ show "always true" hint but not "always false" for instanceof

所以,我使用 IntelliJ IDEA 在 Java 中进行编程,并且我正在试验关键字 instanceof,我的代码最终看起来像这样:

public class Main {

    public static void main(String args[])
    {
        One one = new One();
        One two = new Two();

        if (one instanceof Two) 
        {
            System.out.println(one);
        }

        if (two instanceof Two) 
        {
            System.out.println(one);
        }

    }
}

class One { }

class Two extends One { }

IntelliJ 在 two instanceof Two 行给了我一个提示“[...] 总是正确的”,但是对于 one instanceof Two IntelliJ 没有给我一个“[...] 是总是假的”提示。有谁知道为什么?

更新:已在 IDEA 2018.3 中修复。


(免责声明:IntelliJ IDEA 开发者在此,谁负责此功能)。

简短回答:因为它没有实现。

当我们在数据流分析中跟踪变量的实际类型时,我们使用 TypeConstraint class 描述的模型。它允许我们跟踪两种事实:1)如果变量实际类型是 instanceof something 和 2)如果变量实际类型不是 instanceof something。有了这些事实,我们可以推断在许多情况下总是 true/always false instanceof 例如:

void test(Object foo) {
  if (foo instanceof String) {
    if (foo instanceof Integer) { 
      // always false: "instanceof String" fact is not compatible 
      // with "instanceof Integer"
    }
  }
}

void test(Object foo) {
  if (!(foo instanceof Number)) {
    if (foo instanceof Integer) { 
      // always false: "not instanceof Number" fact is not compatible 
      // with "instanceof Integer"
    }
  }
}

但是对于你的情况,这个模型是不够的。我们需要扩展它来跟踪变量的确切类型。在您的代码中,我们跟踪 oneinstanceof One(与 instanceof Two 事实兼容),尽管从 new 表达式我们可以知道 [=12] 更精确的类型信息=] 是 exactly One。这并不经常使用,因为在大多数情况下(变量是方法参数,变量从方法返回,变量从字段赋值,数组元素,强制转换表达式等)我们无法知道类型是精确类型还是子类型,所以目前的模型是完全令人满意的。我只能想象 exactly One 事实跟踪有用的两种情况:new 表达式(就像你的情况一样)和比较后 obj.getClass() == Xyz.class.

我认为,这是一个可以合理实施的功能。这个我已经考虑过了,但是除了我还有人关心,所以我提交了an issue,所以你可以跟踪它。