This Groovy script looks simple enough:
def a = [].join()
println a
I would expect it to throw MissingMethodException
because join
method requires a parameter, if I'm looking at the right one, but it works just fine.
And here is the source code for that method, so the parameter is definitely not optional.
You know where it fails the way I expect it to? In Jenkins, of course.
So, why does it work? Is there some Groovy convention I don't know about? Or does it actually call a different method?
I think you are providing the parameter, but it is null. You are in the end calling this method in DefaultGroovyMethods class:
public static String join(Iterator<?> self, String separator) {
if (separator == null) {
separator = "";
}
...
While default groovy methods are injected into all Groovy objects (you can find this information here among comments) I assume first parameter is always populated by the fact of injecting it to iterable while the second as you can see is set to be empty string when it is null. Thus [].join()
in my opinion passes empty list and null to the join
method and it effectively means setting empty string as separator.
EDIT: Yes, you are right we could do more digging on the subject. For sure Groovy assumes null was passed when function requiring 1 parameter (but not primitive type) is called without parameters:
def f1(String a){
println a
}
f1() // prints word "null"
Here is some info from somebody who spotted it 8 years ago as well.
I am sure this is your missing puzzle - giving no parameters causes Groovy to pass null when parameter is not of primitive type. I do not know how mechanism of injecting default groovy methods makes possible for join
method to accept Iterable
but String
parameter behaviour should be clear now. Isn't it?