我的项目包含以下代码:
params.stringValue?.trim().replaceAll('aa', 'a')
我们预计,如果params.stringValue
为空,则 trim()
和replaceAll()
都不会被调用。
但是我们在这一行上得到NullPointerException
,说明无法在空对象上调用replaceAll()
。
我们必须将代码更改为:
params.stringValue?.trim()?.replaceAll('aa', 'a')
为什么上面的第一个代码段不起作用?这是Groovy中的一个错误,它在一次遇到null之后继续评估表达式吗?
答案 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