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]
为什么我在第一种情况下会得到 NullPointerException
而在第二种情况下却不会?我正在使用 Groovy 2.3.7。
最佳答案
因为这段代码:
if (!conf.contains('homepage')) { list << conf.trim() }
当条件不满足时,不返回任何内容。没有else
对此if
。如果添加 else
返回一个有意义的值,您将避免异常。
另一方面,无论条件是否满足,三元运算符都会返回一个值,因此以下代码:
conf.contains('homepage') ? list : list << conf.trim()
即使conf
也返回一个实际对象确实包含'homepage'
要了解为什么这是一个问题,请查看 inject
的内容方法确实如此。
引用 Javadoc:
Iterates through the given Collection, passing in the initial value to the 2-arg closure along with the first item. The result is passed back (injected) into the closure along with the second item. The new result is injected back into the closure along with the third item and so on until the entire collection has been used.
现在,让我们看一个稍微修改过的示例。我添加了println
看看闭包参数变成了什么:
['homepages/gg','a','b','c','d'].inject([]) { list, conf -> println "[$list, $conf]"; if (!conf.contains('homepage')) { list << conf.trim() } }
运行此命令会产生:
[[], homepages/gg]
[null, a]
Exception thrown
java.lang.NullPointerException: Cannot invoke method leftShift() on null object
at ConsoleScript9$_run_closure2.doCall(ConsoleScript9:2)
at ConsoleScript9.run(ConsoleScript9:2)
第一次调用采用您作为单个 Object
传递的空数组参数和列表的第一个元素,即 "homepages/gg"
。这将被传递到 if
表达。因为第一个元素"homepages/gg"
确实包含字符串 "homepage"
,if
条件被评估为 false。因为没有else
,没有返回任何内容。
什么都没有,由 null
表示闭包第一次求值返回的引用与列表的下一个元素一起用于第二次求值。
conf
现在等于"a
"并且 list
等于 null
。此外,您可以在 <<
列表 ( null
) 上使用 list << conf.trim()
左移运算符。
因此异常(exception)。
这是一个与有效版本等效的版本:
['homepages/gg','a','b','c','d'].inject([]) { list, conf -> if (!conf.contains('homepage')) { list << conf.trim() } else list }
输出符合预期:
===> [a, b, c, d]
关于groovy - Groovy 注入(inject)中奇怪的 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27005152/