groovy:000> ['homepages/gg','a','b','c','d'].inject([]) { list, conf -> if (!conf.contains('homepage')) { list << conf.trim() } }
ERROR java.lang.NullPointerException:
Cannot invoke method leftShift() on null object
at groovysh_evaluate$_run_closure1.doCall (groovysh_evaluate:3)
groovy:000> ['homepages/gg','a','b','c','d'].inject([]) { list, conf -> conf.contains('homepage') ? list : list << conf.trim() }
===> [a, b, c, d]
Why do I get a NullPointerException
in the first case but not in the second? I am using Groovy 2.3.7.
Because this code:
does not return anything when the condition is not met. There's no
else
to thisif
. If you add anelse
returning a meaningful value, you'll avoid the exception.The ternary operator, on the other hand, does return a value whether or not the condition is met so this code:
returns an actual object even if
conf
does contain'homepage'
To see why this is a problem, take a look at what the
inject
method does.To quote the Javadoc:
Now, let's take a look at a slightly modified example. I added a
println
to see what the closure parameters become:Running this yields:
The first call takes the empty array that you pass as the single
Object
parameter and the first element of the list, namely"homepages/gg"
. This gets passed to theif
expression. Because the first element,"homepages/gg"
does indeed contain the string"homepage"
, theif
condition is evaluated to false. Because there is noelse
, nothing is returned.The nothing, represented by a
null
reference, returned by the first evaluation of the closure is used in the second evaluation, along with the next element of the list.conf
is now equal to"a
" andlist
is equal tonull
. Further on, you use the<<
left shift operator on thenull
list (list << conf.trim()
).Hence the exception.
Here's a version equivalent to the one that works:
The output is as expected: