链接空安全运算符

时间:2015-06-12 12:38:18

标签: groovy nullpointerexception

我的项目包含以下代码:

params.stringValue?.trim().replaceAll('aa', 'a')

我们预计,如果params.stringValue为空,则 trim()replaceAll()都不会被调用。

但是我们在这一行上得到NullPointerException,说明无法在空对象上调用replaceAll()

我们必须将代码更改为:

params.stringValue?.trim()?.replaceAll('aa', 'a')

为什么上面的第一个代码段不起作用?这是Groovy中的一个错误,它在一次遇到null之后继续评估表达式吗?

3 个答案:

答案 0 :(得分:8)

我不认为你的假设是正确的。这个:

params.stringValue?.trim().replaceAll('aa', 'a')

并不意味着:

if(params.stringValue is null)
   dont proceed to trim() and replaceAll()

这意味着:

if(params.stringValue is null)
   skip trim() without complain but pass null to replaceAll()

所以你需要说:

params.stringValue?.trim()?.replaceAll('aa', 'a')

如果传入的参数为null,这将跳过trim()replaceAll()

答案 1 :(得分:8)

您的假设只是部分正确。

? - 运算符在空值的情况下不会中断执行,它会阻止调用当前方法,而是返回null,这就是为什么它是必要的还用?

来保护链的右侧

答案 2 :(得分:5)

这确实是Groovy的工作方式,并且已经咬了others

  

println book?.author?。firstName?.trim()。concat(“很棒。”)

     

...

     

看看这行代码,我确信我对任何偷偷摸摸的NullPointerException都是安全的。如果book,author或firstName为null,我将简单地打印null并且不必担心concat()方法。毕竟,如果trim()方法成功,那么保护它的结果为null是没有意义的。这就是我错的地方。

至少this discussion改变了这一点:

  

a?.b.c //你看到错误吗? ;)

     

我会得到一个NullPointerException。我的意思是,如果你使用null-safe?运算符链式表达式,   你必须在所有属性中使用,因为如果你忘了放在某个地方,你也会得到一个错误。它会   如果Groovy可以检测到,那会很好吗?表达式中的运算符,如果将其注入其他属性中   它看到操作员失踪了。所以,如果你打算这个

     

a?.b?.e.f?.g //我忘了把? .n“f”属性   一个?.b.e.f.g

     

Groovy可以使用像这样的真正的空安全表达式修复它:

     

一个?.B?.E?.F?.G