In this third post dedicated to Java 8 Lambda expressions, we’ll look at the new :: operator introduced to allow method and constructor referencing.
DISCLAIMER: all the details exposed in this post were observed related to the JDK 8 demo version as of July 10th 2012. Since the JDK is still in beta, some assertions may not hold in future
Please note that all the example code in this post can be found on my GitHub repository https://github.com/doanduyhai/Java8_Lambda_In_Details
I Method referencing
With the JDK 8 it is possible to create a lambda expression by aliasing an existing method in a class. For this the new :: operator has been introduced. It is possible to reference a method:
- from its class if it was declared static
- from an instance variable of from the this keyword for non-static methods
public interface MethodReferenceSAM { String process(String input); } public class MethodReference { public static String toUpperStatic(String input) { return input.toUpperCase(); } public String toUpperInstance(String input) { return input.toUpperCase(); } public String toUpperFromThis(String input) { MethodReferenceSAM sam = this::toUpperInstance; return sam.process(input); } public static void main(String... args) { MethodReferenceSAM sam = MethodReference::toUpperStatic; System.out.println("nntstatic method reference = "+sam.process("static_input")); MethodReference methodReference = new MethodReference(); sam = methodReference::toUpperInstance; System.out.println("nntinstance method reference = "+sam.process("instance_input")); System.out.println("nnt"this" method reference = "+methodReference.toUpperFromThis("this_input")); System.out.println(""); } }
The output:
static method reference = STATIC_INPUT
instance method reference = INSTANCE_INPUT
“this” method reference = THIS_INPUT
Pretty straightforward. With this feature, we can create a method (static or not) and possibly assigned it as lambda expression to two different SAM (Single Abstract Method) interface, as long as the method signatures match.
Example
public interface SAM1 { String process(String input); } public interface SAM2 { String differentName(String input); } ... SAM1 sam1 = MethodReference::toUpperStatic; SAM1 sam2 = MethodReference::toUpperStatic;
The above code example can be found on GitHub at https://github.com/doanduyhai/Java8_Lambda_In_Details. Just execute the MethodReference.bat(MethodReference.sh) script
II Constructor referencing
Constructor referencing is quite similar to method referencing. The SAM interface method should have the same signature as the constructor method being used.
public interface ConstructorReferenceSAM<T> { T whatEverMethodName(); } public interface ConstructorReferenceSAMWithArgs<T, U> { T createMeANewObject(U arg); } public interface ConstructorReferenceSAMWithParameterizedArg<T, U> { T magic(List<U> arg); } public class ConstructorReference { private String content; private List<String> contents; public ConstructorReference() { this.content = "created by constructor reference"; } public ConstructorReference(String content) { this.content = content; } public ConstructorReference(List<String> contents) { this.contents = contents; } public String getContent() { return content; } public List<String> getContents() { return contents; } public static void main(String... args) { ConstructorReferenceSAM<ConstructorReference> constructorSam = ConstructorReference::new; System.out.println("nntcontent = "+constructorSam.whatEverMethodName().getContent()); ConstructorReferenceSAMWithArgs<ConstructorReference,String> constructorSamWithArg = ConstructorReference::new; System.out.println("nntcontent by arg = "+constructorSamWithArg.createMeANewObject("created by constructor reference with arg").getContent()); ConstructorReferenceSAMWithParameterizedArg<ConstructorReference,String> constructorSamWithParameterizedArg = ConstructorReference::<String>new; System.out.println("nntcontents size by parameterized arg = "+constructorSamWithParameterizedArg.magic(new ArrayList<String>()).getContents().size()); System.out.println(""); } }
The output:
content = created by constructor reference
content by arg = created by constructor reference with arg
contents size by parameterized arg = 0
For constructor with parameterized arguments, please notice the special syntax for referencing (line 53) ConstructorReference::<String>new;
The above code example can be found on GitHub at https://github.com/doanduyhai/Java8_Lambda_In_Details. Just execute the ConstructorReference.bat(ConstructorReference.sh) script
To be continued …
Pingback: Java – far sight look at JDK 8 | Transylvania JUG
informative post about java 8 lambda.. thanks for sharing.. 🙂
You’re welcomed 🙂
Terrific stuff. Have you considered that this is material that could be submitted on an
official online article database?
Thank you for your remarks.
For the moment, my materials are based on a beta version of lambda and until it is officially released, many things can change.
So honestly I prefer to wait until the lambda is stabilized before putting those articles somewhere.