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.
One thought on “Groovy gotcha: Passing zero arguments to a method that expects one”
Makes sense…kinda. If null is nothing, then foo(null) would be equivalent to foo(); in both cases, we’re calling the method and passing in “nothing.” But this doesn’t work other way around: I cannot define an argument-less method and invoke it with a single null argument. So I suppose the takeaway is: nothing is null but null isn’t nothing.
Yeah what got me though is that it only works for single-argument methods, even when the method takes a second optional parameter. It just seems a little inconsistent and I couldn’t find it documented anywhere.