Constructor References – Functional-Style Programming
Constructor References
A constructor reference is similar to a static method reference, but with the keyword new instead of the static method name, signifying that a constructor of the specified class should be executed. Its purpose of course is to instantiate the class.
We can convert between a constructor reference and a lambda expression using the following rule:
A lambda expression of the form
(args) -> new ClassType(args)
is semantically equivalent to the constructor reference:
ClassType::new
where ClassType is the name of the class that should be instantiated. The class name and the keyword new are separated by the double-colon (::) delimiter.
Which constructor of ClassType is executed depends on the target type of the context, since it determines the arguments that are passed to the constructor.
Execution of the constructor reference sbCR defined at (1) results in the zero-argument constructor of the StringBuilder class to be executed, as evident from the type of the constructor reference.
// () -> StringBuilder
Supplier<StringBuilder> sbLE = () -> new StringBuilder();
Supplier<StringBuilder> sbCR = StringBuilder::new; // (1)
StringBuilder sbRef = sbCR.get();
// Calls new StringBuilder() to create an empty StringBuilder instance.
However, execution of the constructor reference sb4 defined at (2) results in the constructor with the String parameter to be executed, as evident from the type of the constructor reference. The target types at (1) and (2) are different. The target type determines which constructor of the StringBuilder class is executed.
// String -> StringBuilder
Function<String, StringBuilder> sb3 = s -> new StringBuilder(s);
Function<String, StringBuilder> sb4 = StringBuilder::new; // (2)
System.out.println(sb4.apply(“Build me!”)); // Build me!
// Calls new StringBuilder(“Build me!”) to create a StringBuilder instance
// based on the string “Build me!”.
The following code illustrates passing two arguments to a constructor using an appropriate target type—in this case, a two-arity function—that ensures applicable arguments are passed to the constructor.
// (String, String) -> Locale
BiFunction<String, String, Locale> locConsLE
= (language, country) -> new Locale(language, country);
BiFunction<String, String, Locale> locConsCR = Locale::new;
System.out.println(locConsCR.apply(“en”,”US”)); // en_US
// Calls new Locale(“en”, “US”) to create a Locale instance with the specified
// parameter values.
Note that the constructor reference is defined first without any instance being created, and its execution is deferred until later when the functional method of its target type is invoked.