【问题标题】:Why does IDEA report possible NullPointerException?为什么 IDEA 会报告可能的 NullPointerException?
【发布时间】:2018-01-23 21:28:40
【问题描述】:

为什么使用辅助变量进行空值检查可以防止NullPointerException,而直接空值检查则不行?


考虑这两个代码块:

public boolean passwordMatch1(Player player, String password) {
    if (LoggedPlayer.getLoggedPlayer(player) != null) {
        return LoggedPlayer.getLoggedPlayer(player).getPassword().equals(password);
    }
    return false;
}

public boolean passwordMatch2(Player player, String password) {
    LoggedPlayer p = LoggedPlayer.getLoggedPlayer(player);
    if (p != null) {
        return p.getPassword().equals(password);
    }
    return false;
}

他们做的完全一样,方法passwordMatch2使用LoggedPlayer的辅助变量p,而方法passwordMatch1直接检查null。

已知方法 LoggedPlayer.getLoggedPlayer(Player player) 在找不到合适的 LoggedPlayer 实例时返回 null


IDEA 在passwordMatch1 中报告警告:

方法调用“getPassword”可能会产生 'java.lang.NullPointerException

passwordMatch2 没有警告。

IntelliJ IDEA Ultimate 2017.2

【问题讨论】:

  • 如果底层 LoggedPlayer.getLoggedPlayer() 数据结构能够在调用之间进行更改(例如在多线程上下文中),那么 passwordMatch1 中的第二次调用可能会返回空值。

标签: java intellij-idea nullpointerexception


【解决方案1】:

考虑一个可能的(但不好的)LoggedPlayer.getLoggedPlayer 实现。

public static LoggedPlayer getLoggedPlayer(Player player) {
   return Math.random() < 0.500 ? new LoggedPlayer() : null;
}

也就是说getLoggedPlayer可能不是纯的,单独调用它可能返回不同的值。

【讨论】:

    【解决方案2】:

    静态分析存在局限性。通常,静态分析无法可靠地检测和上下文化您已将潜在不安全操作包装在安全检查中。

    词法分析器很简单。他们将标记他们看到的每个符号,然后从那里开始。从那里,他们将无法说:“哦,我们已经检查了此调用”,他们将无法可靠地报告其安全性。

    另一个问题是,如果您的方法不是幂等的,那么无法在静态分析中确定。如果LoggedPlayer.getLoggedPlayer(player) 在任何给定的调用中返回不同的值(例如在@Nick 的精彩示例中),那么词法分析器将错过关于该案例的报告。

    【讨论】:

      猜你喜欢
      • 2014-12-02
      • 2011-07-10
      • 2017-10-08
      • 2012-03-26
      • 2013-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多