Named Parameters in Java
Java doesn’t natively support named parameters, but we can easily have something like:
robot.punch(force(1), speed(100));
Named parameters are very handy when we start having methods with a lot of parameters and we want to allow invoking the method with an arbitrary subset of them, using default values for the rest. A typical symptom when this is needed is when we have a large number of overloaded methods, with various combinations of parameters.
In order to provide this we need something like a NamedParameter class and a few factory methods. While we could easily write our own implementation, we can just use the named-parameters library.
<dependency>
<groupId>me.jaksa</groupId>
<artifactId>named-parameters</artifactId>
<version>0.2</version>
</dependency> We still have to do some manual work. First, for the sake of tidiness, we will create a nested class containing our parameters:
public class GiantRobot { public static class PunchParams { } }
…and inside it an enum with the names of our parameters:
public class GiantRobot { public static class PunchParams { enum Names {FORCE, SPEED, EXCLAMATION} } }
Now we need the factory methods for our parameters inside the PunchParams class:
import static me.jaksa.namedparameters.GiantRobot.PunchParams.Names.*;
import static me.jaksa.namedparameters.Params.*;
...
public static Param force(int f) { return param(FORCE, f); }
public static Param speed(int s) { return param(SPEED, s); }
public static Param exclamation(String e) { return param(EXCLAMATION, e); } Now we can define our method taking a vararg of Param classes:
public void punch(Param... params) {
int force = getParam(params, FORCE, 10);
int speed = getParam(params, SPEED, 3);
String exclamation = getParam(params, EXCLAMATION, "@#$%!" );
System.out.printf("Robot, punching with force %d and speed %d, says: %s\n", force, speed, exclamation);
} And we’re done. The getParam() method is statically imported from the Params class and it returns the value of the parameter with the specified name or the specified default value if the parameter is not there.
Now we can use the method from other classes and specify any combination of parameters in any order:
import static me.jaksa.namedparameters.GiantRobot.PunchParams.*;
...
robot.punch();
robot.punch(force(5));
robot.punch(speed(30));
robot.punch(force(1), speed(100));
robot.punch(speed(100), force(1));
robot.punch(force(12), exclamation("Take this!")); There are more tricks than what we’ve seen here. We can have methods which have a combination of mandatory, optional or even unnamed parameters, add more type safety, combine parameters for different methods or safely separate parameters with the same name but different type. We will take a look at more advanced uses in the future.