Named parameters in Java (bgl-style)
Sometimes one would like to have the ability to have named parameters in Java. During a lecture in how to use the boost graph library I came across how named parameters are implemented in the BGL. How to use named parameters in bgl is explained here. Let me introduce a example why one might need, named parameters.
public class Example {
public static void outputName(String title, String firstName, String middleName, String lastName) {
System.out.print((title != "" ? title+". " : "Mr./Mrs. "));
System.out.print((firstName != "" ? firstName+" " : ""));
System.out.print((middleName != "" ? middleName.charAt(0)+". " : ""));
System.out.print(lastName);
System.out.println();
}
public static void main(String[] args) {
outputName("Dr", "Franz", "Peter", "Frosch");
outputName("", "Heidi", "", "Peter");
outputName("Dr", "", "", "Müller");
outputName("", "Beat", "Sepp", "Wolf");
}
}
This example shows how a call to a method with a lot of parameters can be hard to read and easy to misunderstand and can be a source of errors. So it would be nice if one could name the parameters as bellow.
/* NOT WORKING CODE*/
public class ExampleNotWorkingNamed {
public static void outputName(String title = "", String firstName = "", String middleName = "", String lastName="") {
System.out.print((title != "" ? title+". " : "Mr./Mrs. "));
System.out.print((firstName != "" ? firstName+" " : ""));
System.out.print((middleName != "" ? middleName.charAt(0)+". " : ""));
System.out.print(lastName);
System.out.println();
}
public static void main(String[] args) {
outputName(title="Dr", first="Franz", middle="Peter", last="Frosch");
outputName(first="Heidi", last="Peter");
outputName(title="Dr", last="Müller");
outputName(first="Beat", middle="Sepp", last="Wolf");
}
}
In some programing language something like this does work, unfortunately in Java it doesn't. At this moment we come to the point where we implement the named parameters like in bgl. A call does look then like bellow:
outputName(first("Beat").middle("Sepp").last("Wolf"));
The full code for the same example with named parameters does look like this:
import api.NamedParameterNames;
import static api.NamedParameterNamesFactory.*;
public class NamedExample {
public static void outputName(NamedParameterNames names) {
System.out.print((names.getTitle() != null ? names.getTitle()+". " : "Mr./Mrs. "));
System.out.print((names.getFirst() != null ? names.getFirst()+" " : ""));
System.out.print((names.getMiddle() != null ? names.getMiddle().charAt(0)+". " : ""));
System.out.print((names.getLast() != null ? names.getLast() : ""));
System.out.println();
}
public static void main(String[] args) {
outputName(title("Dr").first("Franz").middle("Peter").last("Frosch"));
outputName(first("Heidi").last("Peter"));
outputName(title("Dr").last("Müller"));
outputName(first("Beat").middle("Sepp").last("Wolf"));
}
}
Afterwards we show that we need to implement a Factory which static methods are imported over the static import in the mail file. They all return an object of the type NamedParameterNames which does contain exactly the same method as the factory and does return an object as well so that we can use method chaining. The code does look like this:
package api;
public class NamedParameterNamesFactory {
public static NamedParameterNames title(String title) {
NamedParameterNames p = new NamedParameterNames();
p.title(title);
return p;
}
public static NamedParameterNames first(String firstname) {
NamedParameterNames p = new NamedParameterNames();
p.first(firstname);
return p;
}
public static NamedParameterNames middle(String middle) {
NamedParameterNames p = new NamedParameterNames();
p.middle(middle);
return p;
}
public static NamedParameterNames last(String last) {
NamedParameterNames p = new NamedParameterNames();
p.last(last);
return p;
}
}
package api;
public class NamedParameterNames {
private String title;
private String first;
private String middle;
private String last;
protected NamedParameterNames(){
super();
}
public String getTitle() {
return title;
}
public NamedParameterNames title(String title) {
this.title = title;
return this;
}
public String getFirst() {
return first;
}
public NamedParameterNames first(String firstname) {
this.first = firstname;
return this;
}
public String getMiddle() {
return middle;
}
public NamedParameterNames middle(String middle) {
this.middle = middle;
return this;
}
public String getLast() {
return last;
}
public NamedParameterNames last(String last) {
this.last = last;
return this;
}
}
There are some advantages and some disadvantages of doing this. Start with the advantages:
- Calls to the method are easy to read
- Might reduce error by wrong calls
But there are also quite some disadvantages:
- A lot of code to write for the factory and the parameter object (so this might only pay off if the API get used by a lot of people)
- Not all java-programmer might understand this and the might misuse the API code be writing ugly code. A more "java-ish" way of doing this is the builder pattern out of Josh Bloch's "Effective Java 2nd Edition".
- If you need a lot of parameter in your method might be a indicator that your OO design is bad. Think about it again!
More about the named parameter idiom on Stackoverflow





