【问题标题】:Mysterious NullPointerException神秘的 NullPointerException
【发布时间】:2013-09-24 08:29:05
【问题描述】:

我有以下代码。它工作正常。没有例外等。我正在循环使用标准查询检索到的 JPA 实体对象列表(因此列表中没有任何 null 对象)。

for (PeriodicalTable periodical : resultsP){
        stringFor.add(periodical.getReference());
        site = em.find(SiteTable.class, periodical.getSiteID());
        if (site != null && site.getPostcode() != null && !site.getPostcode().equals("")){
            tempString = site.getPostcode().replaceAll("\\s+", " ");
            periodical.setPostcode(tempString.trim());                       
            }    
        }

现在,我在if 语句中添加了一条语句,这样只有在循环列表中的对象具有contractManagerID0 时才会触发一行。标记如下;

for (PeriodicalTable periodical : resultsP){
        if(periodical.getContractManagerID()==0) //<---- HERE!!!!
        {
            stringFor.add(periodical.getReference());
        }
        site = em.find(SiteTable.class, periodical.getSiteID());           
        if (site != null && site.getPostcode() != null && !site.getPostcode().equals("")){
            tempString = site.getPostcode().replaceAll("\\s+", " ");
            periodical.setPostcode(tempString.trim());                       
            }                
        }

经过一些调试后,我将异常隔离为来自 if 语句本身(标记为“HERE”),但我不明白这是怎么回事。我们知道列表中没有 null 对象,否则即使没有 if 语句它也无法工作,但没有它它也能正常工作。我完全迷路了。

【问题讨论】:

  • getContractManagerID() 返回什么?
  • 您确定periodical.getContractManagerID() 本身不为空吗?
  • getContractManagerID() 返回一个整数。数据库中没有空值,但即使有if语句也不会被满足,它肯定会继续吗?
  • @Rudi Kershaw;它很可能返回一个整数,但一个整数可以为空。 (参见 int)。你需要检查一下。

标签: java exception jpa if-statement nullpointerexception


【解决方案1】:

这里唯一的可能是periodical.getContractManagerID()正在返回null

比较 null == 0 会给你一个 NullPointerException

改为这样做:

if (periodical.getContractManagerID() == null || 
    periodical.getContractManagerID() == 0)

【讨论】:

  • 试过了,效果很好。谢谢你。但它确实提出了一个问题。如果 SQL 表的所有 ContractManagerID 的值都是 0,为什么它会返回一些 0 和一些空值,而不是全一个?
  • @Rudi Kershaw:也许这就是数据库视图表示空值的方式。
  • 可能,我想...但是从 Netbeans 的数据库中可以看到其他空值。猜猜这一点将不得不成为一个谜。
【解决方案2】:

有一个相当简单的方法可以找出答案:

  • HERE 行中设置断点。当 Eclipse(我假设您使用 Eclipse)调试器弹出时,选择periodical 变量并按Ctrl + Shift + I(这称为“检查”)。如果它不为空,则评估periodical.getContractManagerID()。应该是null

这意味着您没有使用原语来存储该数字。您应该使用原语,添加合理的默认值或检查null

如果您的PeriodicalTable 类中有Integer,则意味着它可以是null

【讨论】: