这是与Groovy安全导航运营商相关的NPE相关行为吗?

时间:2009-10-22 01:57:27

标签: groovy

我今天的代码中遇到了一个异常,其中trim()在执行someString?.toLowerCase().trim()之类的操作时会抛出NPE。这让我很好奇,因为我认为安全导航操作会在null后立即中断而不是继续调用链中的东西。所以在命令行groovy中修补一下......

groovy> def a = null
groovy> def getB = {
groovy> return 'b'
groovy> }
groovy> def getC = {
groovy> return 'c'
groovy> }
groovy> def var1 = a?.b?.c
groovy> var1

===> null

哪个都很好,花花公子。但是删除了b上的安全导航操作,并且......

groovy> def a = null
groovy> def getB = {
groovy> return 'b'
groovy> }
groovy> def getC = {
groovy> return 'c'
groovy> }
groovy> def var2 = a?.b.c
groovy> var2
groovy> go
Caught: java.lang.NullPointerException: Cannot get property: c on null object
        at CommandLine.run(CommandLine.groovy:10)

这里发生了什么? a为空,所以如果有的话,NPE应该被b抛出,但这就是安全导航操作的用途。我原本期望执行在此时停止并将null返回var2,但似乎null传递到b,导致c到NPE。

我对安全导航操作的理解是错误的,还是Groovy中的错误?谢谢大家!

1 个答案:

答案 0 :(得分:4)

安全导航操作符不像布尔表达式短路。它与整个表达无关。它只保护紧挨着它的一个点引用。

对于这个例子:

a?.b.c

这是正确的:

java.lang.NullPointerException: Cannot get property: c on null object
        at CommandLine.run(CommandLine.groovy:10)

正在发生的事情是,安全导航操作符的工作方式与表达式的第一部分相同,防止“a”变量的可能空值,从而保持对a.anything的任何引用不会出错。 NPE。因此,表达式的“a.b”部分减少为null,我们现在有:

null.c

当然,当Groovy继续评估缺少问号意味着没有什么可以阻止它提高NPE。