Java 当没有与查询匹配的内容时,为什么会出现NPE异常

Java 当没有与查询匹配的内容时,为什么会出现NPE异常,java,datanucleus,Java,Datanucleus,使用以下datanucleus查询,execute方法在没有任何内容与查询匹配时抛出NullPointerException StringBuilder query = new StringBuilder("select avg(millis) from "); query.append(clazz.getName()); query.append(String.format(" where name.equals('%s')", name)); query.append(String.form

使用以下datanucleus查询,execute方法在没有任何内容与查询匹配时抛出NullPointerException

StringBuilder query = new StringBuilder("select avg(millis) from ");
query.append(clazz.getName());
query.append(String.format(" where name.equals('%s')", name));
query.append(String.format(" && database.equals('%s')", props.get("database")));
query.append(String.format(" && version.equals('%s')", props.get("version")));
Double ave = (Double) pm.newQuery(query.toString()).execute();
NPE如下所示:

at org.datanucleus.query.evaluator.memory.SetExpression.avg(SetExpression.java:414)
at org.datanucleus.query.evaluator.memory.InMemoryExpressionEvaluator.getValueForInvokeExpression(InMemoryExpressionEvaluator.java:719)
at org.datanucleus.query.evaluator.memory.InMemoryExpressionEvaluator.processInvokeExpression(InMemoryExpressionEvaluator.java:562)
at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compilePrimaryExpression(AbstractExpressionEvaluator.java:200)
...
我在调试器中花了一些时间,可以看到传递给SetExpression构造函数的集合是空的。这最终导致SetExpression.avg方法中出现NPE


当集合为空时,“avg”的行为是否正确?如果没有与查询匹配的内容,“平均”返回值是什么,文档中的内容是不明确的,但我不希望出现NPE。

在与@Mike Samuel进行了长时间的讨论后,我想这是一种可能的解决方案:

而不是

Double ave = (Double) pm.newQuery(query.toString()).execute();
试一试

根据讨论,错误可能存在于您正在使用的库中,在本场景中,该库将尝试取消对空值的装箱,以将其转换为
双精度
。当然,如果没有演员,那就更好了。因此,如果该方法返回一个
浮点值
(例如):


我认为这可能被解释为datanucleus core 3.2.13中的一个bug,假设avg投影的期望行为是在没有选定记录的情况下返回0

其SetExpression.avg的实现如下:

if (itemIterator == null)
{
    return 0.0d;
}
我不是100%确定,但我认为如果更改为以下内容,它将以正确的方式解决NPE,如果未选择任何记录,则返回0

if (itemIterator == null || !iterator.hasNext())
{
    return 0.0d;
}

堆栈跟踪中的行号与您发布的代码行有何关系?@DigCamara,将
null
强制转换为引用类型不会引发NPE,因为
null
是任何引用类型的有效值。@Mike Samuel,幸好我没有将其标记为答案。无知在战斗@Mike Samuel:但是,这是否适用:“由于对空引用进行了取消装箱转换而导致的NullPointerException。”(from)@DigCamara,可能以后会取消对
ave
的装箱,但发布的代码中没有取消装箱。只是有很多SQL注入漏洞。没有为空样本列表定义平均值
Double.NaN
将是一个更合适的值。我不同意您的观点,但当前代码在迭代器运行时返回0null@whytten很公平。他们有一个实现错误,可能还有一个规范错误。
if (itemIterator == null)
{
    return 0.0d;
}
if (itemIterator == null || !iterator.hasNext())
{
    return 0.0d;
}