我今天的代码中遇到了一个异常,其中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中的错误?谢谢大家!
答案 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。