Overloaded Methods, Varargs, Single Arguments and Recursion in Java
This is another “documenting my own stupidity” post. I’m hoping the public self-ridicule will help stop me from being so short sighted in the first place.
I’m sure lots of people use the following pattern. You write a method that takes a heap of arguments, but which can have some defaults. You then introduce one or more overloads, with progressively fewer arguments, and sensible defaults filled in.
To avoid duplication of your actual logic, the overloads only add the defaults, and then call the original, many argumented method. For example:
Original pattern:
123456789
publicStringdoSomething(){//No logic here, just a call to the next method down with a default.returndoSomething("default-value");}publicStringdoSomething(Stringargument){//does something - very complicated, you don't want to duplicate this.returnargument+" or summat";}
So that was fine, But then things moved on, and I needed to introduce a little more complexity in the form of an unknown number of arguments using varargs. So I simply added a new method, migrated the logic and refactored to something like this:
12345678910111213141516
//we refactor the other methods - still don't want duplicationpublicStringdoSomething(){//No logic here, just a call to the next method down with a default.returndoSomething("default-value");}publicStringdoSomething(Stringargument){//want to call the varargs based method below:returndoSomething(argument);//Hmm - that's not going to work - it's just going to recurse.}publicStringdoSomething(String...lotsOfArguments){//does something - even more very extremely complicated, and you still don't want duplicationreturnStringUtils.join(authors,",")+" or summat";}
The middle method in the above snippet doesn’t work (and throws infinite recursion warnings) as it simply calls itself, rather than the varargs method with a single argument.
What confused me is that I googled about a bit, and couldn’t find any discussion of what to do in this case, so I tried the following, and felt pretty pleased with myself.
12345
publicStringdoSomething(Stringargument){//want to call the varargs based method with the logic in:returndoSomething(newString[]{argument});//take that Java}
But of course – I was completely missing the point. I didn’t need the single argument overload as calls with a single argument already call the varargs overload! So it just needs deleting – and happy days.
12345678910
//Delete the single string argument - it was a rudundant fossil anyway.publicStringdoSomething(){//No logic here, just a call to the next method down with a default.returndoSomething("default-value");}publicStringdoSomething(String...lotsOfArguments){//does something - even more very extremely complicated, and you still don't want duplicationreturnStringUtils.join(authors,",")+" or summat";}
12
//calling code: works fineStringresut=doSomething("single string");
Works fine if you delete the single argument method. Of course. Face palm.