Troubleshooting & How-Tos 📡 🔍 Programming

Java/Groovy Overloading and Null Parameters

More fun with NullPointerExceptions!

In Java, as with many programming languages, you can overload a method so it can take different parameters. You just give it the same name, return type, access and other parts of the signature.

For example, you might want to have something like (I’m simplifying here):

class Record {
	...
	public void setDate(Date newDate){
		...
	}
	public void setDate(String dateString) {
		// parse the string the way *you* want it parsed
		...
	}
}

So now you can call myRecord.setDate(myDate) or myRecord.setDate('October 26, 2023') and it’ll run the appropriate method. Great! Super convenient! You can even just call it inside a function that might have a Date or might have a String. Maybe it was passed an Object, or maybe you’re using Groovy with the def keyword, maybe you’re trying to use the same class for both Grails binding and JSON parsing, whatever. The point is, even if the calling method doesn’t know or care which class the parameter is, Java will figure it out and use the right method.

Great!

Until you pass it a null value.

That’s when you get the NPE.

Why? Because all Java can tell is that it’s null. It doesn’t have any way to decide whether to call the method that wants a Date or the method that wants a String.

Ideally you’d refactor so you know there will always be an actual value in there. If the input can’t be null, then you’ll never encounter the error. But if you’re using external input – say the JSON example I gave earlier – there’s a decent chance this might happen.

You could explicitly check for null every time you call the method, but that’s annoying, less maintainable, and defeats the whole purpose of overloading the method in the first place.

You could change it to setDate(Object newDate) and put a switch statement inside the method, and check what class newDate is yourself, but that’s kind of silly when the programming language can (mostly) do that for you.

Or, you can overload the method with one more path that only accepts nulls:

public void setDate(Nullable alwaysNull) {
	// clear, ignore, or whatever you want to do here
	...
}

It feels hacky. But it works, at least in Groovy. (TODO: Double-check that it works in plain Java too.)

This took more investigation and trial-and-error than I wanted because

  • Most of the documentation and Q&A discussion I could find focused on why the overload fails when passed null. Short version: Java chooses the most specific class compatible with both the input and the method signature, but classes like Date and String are separate branches. Neither inherits from the other, so neither is more specific, so Java can’t determine which it should use.
  • Most of the “solutions” I found were basically “don’t do that” or “refactor your code so it can’t happen.”
  • I didn’t have control over how the method was going to be called, so the only refactoring I could do was inside the class anyway.
  • I couldn’t remember the name of the Nullable class, and searching for various combinations of “null,” “class,” “object,” “NullPointerException,” “overloading”/“overloaded,” “groovy” and “java” mostly picked up stuff about how things handle null values (or don’t), how you can add optional parameters in Groovy, and the many ways Groovy interprets null.