Groovy gotcha: Passing zero arguments to a method that expects one
I was recently adding a parameter to a legacy method, and after updating all the callers of the method, I found that I was still getting a MethodMissingException. That was strange, since the old method took one required parameter, and the exception was being thrown on a line which called a method of the same name with no arguments. My first reaction was that it couldn’t possibly be the same method I was updating, but… I was wrong. Apparently Groovy will compile just fine in certain scenarios where no arguments are passed to a method that expects one.
For example, only the second call below throws a MissingMethodException:
The first one will compile and run without issue, and will print “null” to the console. That’s unexpected, but it makes sense given that we accept an object (this works with any object, as far as I can tell). The second call fails because it expects a primitive, and I guess Groovy does not resolve to pass any “default” values to it. You can try this out in the Groovy web console, if you want to play around with it yourself.
Upon compilation, you may think that Groovy implicitly creates a zero-arg method similar to having an optional parameter, but examining the class’s methods proves otherwise; whereas the required parameter version only yields public void SomeClass.doSomething(java.lang.Object), the optional one really does compile to two methods: public void SomeClass.doSomething(java.lang.Object) and public void SomeClass.doSomething().
The fact that there is no zero-arg method means that this is a special case, rather than a rule of passing n-1 arguments to a method. This is clearly demonstrated if we try to add another parameter to our method, and call it with only one argument. This is true even if the new parameter is optional with a default value:
The first call above will throw a MethodSelectionException, while the second will throw a MissingMethodException but we are mostly back in the realm of “expected” Java behavior.
This may be common knowledge to some, but other developers I spoke to were not aware of this behavior. It’s certainly interesting, but I wouldn’t advocate it as best practice. It seems clearer and more maintainable to simply make a parameter optional, rather than relying on Groovy to pass the null value. However, if you’re refactoring a method signature and find yourself getting some unexpected behavior, hopefully this post can shed some light.