Java 改进的Intellij代码检查可能会产生NullPointerException警告

Java 改进的Intellij代码检查可能会产生NullPointerException警告,java,intellij-idea,annotations,code-inspection,Java,Intellij Idea,Annotations,Code Inspection,我有一个类,它有一个hasField函数检查字段是否存在且不为null,还有一个getField函数返回字段的值(如果不存在则为null) 在我的代码中,当我在检查hasField之后立即调用getField时,我知道getField不会返回null,但是IDE检查(常量条件和异常)不知道这一点。我得到一堆方法方法名可能会产生空点异常 我正试图找到一个干净的方法让这个警告消失 解决办法 以下是我可以做的一些变通方法,但我发现所有这些方法都有问题: 用对象包围getField。requireNot

我有一个类,它有一个
hasField
函数检查字段是否存在且不为null,还有一个
getField
函数返回字段的值(如果不存在则为null)

在我的代码中,当我在检查
hasField
之后立即调用
getField
时,我知道getField不会返回null,但是IDE检查(常量条件和异常)不知道这一点。我得到一堆方法
方法名
可能会产生
空点异常

我正试图找到一个干净的方法让这个警告消失

解决办法

以下是我可以做的一些变通方法,但我发现所有这些方法都有问题:

  • 对象包围
    getField
    。requireNotnull
    ,代码将是不可操作的。我们不希望这样做,因为这样会使代码的可读性稍差
  • 在我知道安全的情况下抑制警告。同样,这不是首选,因为这将在我们的代码中的许多地方发生
  • 忽略警告。在这种情况下,我们可能会错过合法的警告,因为警告部分太吵了
  • 理想溶液

    我是否能够以某种方式设置警告,如果
    hasField
    为真,那么
    getField
    将返回非空值?我研究了一下,但在这里做我想做的事情似乎超出了@Contract的支持范围

    代码示例

    下面是演示此问题的最低工作代码示例:

    import javax.annotation.Nullable;
    
    public class Hello {
    
      private Hello(){}
      public static void main(String[] args) {
        TestClass test1 = new TestClass(null);
        if (test1.hasSample()) {
          System.out.println(test1.getSample().equals("abc"));
        }
     }
    }
    
    class TestClass {
      private final String sample;
    
      TestClass(String field) { this.sample = field; }
    
      boolean hasSample() { return sample != null; }
    
      @Nullable public String getSample() { return sample; }
    }
    
    我得到以下警告

    方法调用
    equals
    可能会产生
    NullPointerException

    理想情况下,当hasSample为true时,我希望能够告诉IDE getSample不为null。

    我是负责此子系统的IntelliJ IDEA开发人员


    不,现在不可能了。假设您不能更改API,没有比您已经列出的可能解决方案更好的解决方案了。我们拥有的最接近的东西是非常平凡的方法的内联。但是,它仅在以下情况下有效:

    • hasSample()
      getSample()
      这样的方法是从同一个类调用的
    • 无法重写被调用的方法(private/static/final/在final类中声明)
    例如,此功能适用于以下代码:

    final类TestClass{//如果删除final,警告将再次出现
    私人最终字符串样本;
    TestClass(字符串字段){this.sample=field;}
    布尔hasSample(){返回样本!=null;}
    @可空
    公共字符串getSample(){return sample;}
    @凌驾
    公共字符串toString(){
    if(hasSample()){
    return“TestClass:+getSample().trim();//此处没有关于trim()调用的警告
    }
    返回“TestClass”;
    }
    }
    
    目前,我只能建议您将API重构为如下选项:

    import java.util.Optional;
    公共课你好{
    私有Hello(){}
    公共静态void main(字符串[]args){
    TestClass test1=新的TestClass(null);
    test1.getSample().ifPresent(s->System.out.println(s.equals(“abc”));
    //或者fancier:test1.getSample().map(“abc”::equals).ifPresent(System.out::println);
    }
    }
    最终类TestClass{
    私人最终字符串样本;
    TestClass(字符串字段){this.sample=field;}
    公共可选getSample(){return Optional.ofNullable(sample);}
    }
    
    感谢您的快速回复。现在我决定忽略这些警告。