Null-Safe Operator Chain

My project has the following code:

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

We expected that if params.stringValue was null, then both trim() and replaceAll() would not be called.

However, we got a NullPointerException on this line, saying that replaceAll() could not be called on a null object.

We had to change the code like this:

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

Why doesn't the first code snippet above work? Is it a mistake in Groovy that he continues to evaluate an expression after one zero has been encountered?

+5
source share
3 answers

This is the way Groovy works, indeed, and bit others :

println book? .author? .firstName? .trim (). concat ("is great.")

...

By looking at this line of code, I am sure that I was safe from any hidden NullPointerException. If the book, author, or firstName is null, I will just end up printing null and not worry about the concat () method. After all, if the trim () method succeeds, it makes no sense to protect its result by zero. And this is where I was wrong.

At least this discussion to change this:

a? .bc // Do you see an error ?;)

I will get a NullPointerException. I mean, if you use a null safe ?. the operator in a chain expression, you should use in all properties, because if you forget to stand up, you will also get an error. Will it be good if Groovy can detect ?. the operator in the expression, and it enters it into other properties if it sees that the operator is missing. So, if you type this

a? .b? .ef? .g // I forgot to put? .. n the property "f" is worth? .befg

Groovy can fix it with a real null-safe expression, for example:

a? .b? .e? .f? .g

+4
source

I do not think your assumption was correct. this is:

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

does not mean:

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

It rather means:

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

so you need to say:

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

This will skip both trim() and replaceAll() if the input argument is null.

+8
source

Your assumption is only partially correct.

The operator ? does not interrupt execution in case of null, it blocks the call of the current method and instead returns null , therefore it is also necessary to protect the right side of the chain with ?

+8
source

All Articles